linux管道阻塞代码,linux中的管道
管道是一種最基本的IPC機制,由pipe函數創建:#include?
int?pipe(int?filedes[2]);
調用pipe函數就是在內核區開辟一塊緩沖區(稱為管道)。filedes[0]指向管道的讀端,filedes[1]指向管道的寫端。管道實際上就是一個打開的文件。pipe函數成功返回0,失敗返回-1.
如何用管道實現兩個進程間的通信?
1.父進程調用pipe函數開辟管道,得到兩個文件描述符指向管道的兩端。
2.父進程調用fork()創建子進程,那么子進程也有兩個文件描述符指向該管道。
3.父進程關閉管道讀端,子進程關閉管道寫端。父進程可以往管道寫,子進程可以從管道
讀,管道是環形隊列實現的,數據從寫端流,從讀端流出,這樣就實現了進程間通信。
代碼實現:#include?
#include?
#include?
#include?
int?main()
{
int?_pipe[2];
int?ret?=?pipe(_pipe);
if?(ret?==?-1){
printf("create?pipe?error!?errno?code?is?:?%d\n",?errno);
return?1;
}
pid_t?id?=?fork();
if?(id?
printf("fork?error!");
return?2;
}
else?if?(id?==?0){?//child
close(_pipe[0]);
int?i?=?0;
char?*_mesg_c?=?NULL;
while?(i<100){
_mesg_c?=?"i?am?child!";
write(_pipe[1],?_mesg_c,?strlen(_mesg_c)?+?1);
sleep(1);
i++;
}
}
else{?//father
close(_pipe[1]);
char?_mesg[100];
int?j?=?0;
while?(j<100){
memset(_mesg,?'\0',?sizeof(_mesg));
read(_pipe[0],?_mesg,?sizeof(_mesg));
printf("%s\n",?_mesg);
j++;
}
}
return?0;
}
使用管道需要注意的4中情況:
1. 如果所有指向管道寫端的文件描述符都關閉了(管道寫端的引用計數等于0),仍然有
進程從管道的讀端讀數據,那么管道中剩余的數據都被讀取后,再次read會返回0,就像
讀到件末尾樣。
測試代碼:#include?
#include?
#include?
#include?
#include?
int?main()
{
int?_pipe[2];
int?ret?=?pipe(_pipe);
if?(ret?==?-1){
printf("create?pipe?error!?errno?code?is?:?%d\n",?errno);
return?1;
}
pid_t?id?=?fork();
if?(id?
printf("fork?error!");
return?2;
}
else?if?(id?==?0){?//child
close(_pipe[0]);
int?i?=?0;
char?*_mesg_c?=?NULL;
while?(i<10){
_mesg_c?=?"i?am?child!";
write(_pipe[1],?_mesg_c,?strlen(_mesg_c)?+?1);
sleep(1);
i++;
}
close(_pipe[1]);
}
else{?//father
close(_pipe[1]);
char?_mesg[100];
int?j?=?0;
while?(j<100){
memset(_mesg,?'\0',?sizeof(_mesg));
int?ret?=?read(_pipe[0],?_mesg,?sizeof(_mesg));
printf("%s?:?code?is?:?%d\n",?_mesg,?ret);
j++;
}
if?(waitpid(id,?NULL,?0)
{
return?3;
}
}
return?0;
}
2. 如果有指向管道寫端的文件描述符沒關閉(管道寫端的引用計數大于0),持有管道寫
端的進程也沒有向管道中寫數據,這時有進程從管道讀端讀數據,那么管道中剩余的數
據都被讀取后,再次read會阻塞,直到管道中有數據可讀了才讀取數據并返回。
測試代碼:#include?
#include?
#include?
#include?
#include?
int?main()
{
int?_pipe[2];
int?ret?=?pipe(_pipe);
if?(ret?==?-1){
printf("create?pipe?error!?errno?code?is?:?%d\n",?errno);
return?1;
}
pid_t?id?=?fork();
if?(id?
printf("fork?error!");
return?2;
}
else?if?(id?==?0){?//child
close(_pipe[0]);
int?i?=?0;
char?*_mesg_c?=?NULL;
while?(i<20){
if?(i?
_mesg_c?=?"i?am?child!";
write(_pipe[1],?_mesg_c,?strlen(_mesg_c)?+?1);
}
sleep(1);
i++;
}
close(_pipe[1]);
}
else{?//father
close(_pipe[1]);
char?_mesg[100];
int?j?=?0;
while?(j<20){
memset(_mesg,?'\0',?sizeof(_mesg));
int?ret?=?read(_pipe[0],?_mesg,?sizeof(_mesg));
printf("%s?:?code?is?:?%d\n",?_mesg,?ret);
j++;
}
if?(waitpid(id,?NULL,?0)
{
return?3;
}
}
return?0;
}
3. 如果所有指向管道讀端的文件描述符都關閉了(管道讀端的引用計數等于0),這時有進
程向管道的寫端write,那么該進程會收到信號SIGPIPE,通常會導致進程異常終。
測試代碼:#include?
#include?
#include?
#include?
#include?
int?main()
{
int?_pipe[2];
int?ret?=?pipe(_pipe);
if?(ret?==?-1){
printf("create?pipe?error!?errno?code?is?:?%d\n",?errno);
return?1;
}
pid_t?id?=?fork();
if?(id?
printf("fork?error!");
return?2;
}
else?if?(id?==?0){?//child
close(_pipe[0]);
int?i?=?0;
char?*_mesg_c?=?NULL;
while?(i<20){
if?(i?
_mesg_c?=?"i?am?child!";
write(_pipe[1],?_mesg_c,?strlen(_mesg_c)?+?1);
}
sleep(1);
i++;
}
}
else{?//father
close(_pipe[1]);
char?_mesg[100];
int?j?=?0;
while?(j<3){
memset(_mesg,?'\0',?sizeof(_mesg));
int?ret?=?read(_pipe[0],?_mesg,?sizeof(_mesg));
printf("%s?:?code?is?:?%d\n",?_mesg,?ret);
j++;
}
close(_pipe[0]);
sleep(10);
if?(waitpid(id,?NULL,?0)
{
return?3;
}
}
return?0;
}
4. 如果有指向管道讀端的文件描述符沒關閉(管道讀端的引用計數大于0),持有管道讀
端的進程也沒有從管道中讀數據,這時有進程向管道寫端寫數據,那么在管道被寫滿時
再次write會阻塞,直到管道中有空位置了才寫入數據并返回。
總結
以上是生活随笔為你收集整理的linux管道阻塞代码,linux中的管道的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ping连接linux无法访问目标主机,
- 下一篇: Linux中Apache2fail,ap