您好,登錄后才能下訂單哦!
現在linux使用的IPC(Inter-Process Communication,進程間通信)方式有以下幾種:
-(1)管道(pipe)和匿名管道(FIFO)
-(2)信號(signal)
-(3)消息隊列
-(4)共享內存
-(5)信號量
-(6)套接字(socket)
管道是Unix中最古老的進程間通信的形式。我們把一個進程連接到另一個進程的一個數據流成為一個“管道”。
只能用于父子進程或者兄弟進程之間(具有親緣關系的進程)進行通信。
#include <unistd.h>
int pipe(int pipefd[2]);
功能:創(chuàng)建無名管道
參數:文件描述符組。fd[0]表示讀端,fd[1]表示寫端。
返回值:成功返回0,失敗返回錯誤代碼
也就是說,在fork()之前pipe(),就可以使得父子進程之間建立起一個管道,畫個圖:
父子進程都會打開5個文件描述符,除了默認的0、1、2。還有fd[0]、fd[1]。測試一下,就會知道這兩個文件描述符為3、4。
寫串代碼用一用:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main()
{
int fd[2];
int retByte;
pid_t pid;
char buf[20] = "";
pipe(fd); /*創(chuàng)建無名管道*/
//printf("%d,%d\n",fd[0],fd[1]);
pid = fork();
if(pid == -1)
{
perror("create fork");
return -1;
}
if(pid == 0)
{
//子進程,寫端,使用fd[1]
//close(fd[0]);
//close(fd[1]);
while(1)
{
scanf("%s",buf);
if( write(fd[1],buf,strlen(buf)) == -1)
{
perror("write");
return -1;
}
memset(buf,0,20);
if(read(fd[0],buf,5) > 0 )
{
printf("child-read msg: %s\n",buf);
}
}
}
else
{
//父進程,讀端,使用fd[0]
while(1)
{
memset(buf,0,20);
retByte = read(fd[0],buf,5);//每次只讀5個
if( retByte == -1)
{
perror("read");
return -1;
}
if(retByte > 0)
{
printf("parent-read msg: %s\n",buf);
}
}
}
return 0;
}
運行結果:
那么,如果沒有讀端呢?也就是父子進程的fd[0]都關閉了,會有什么現象呢?
void handler(int no)
{
printf("SIGPIPE.\n");
}
int main()
{
int fd[2];
int retByte;
int rlt;
pid_t pid;
char buf[20] = "";
rlt = pipe(fd); /*創(chuàng)建無名管道*/
//printf("%d,%d\n",fd[0],fd[1]);
signal(SIGPIPE,handler);
if(rlt != 0)
{
perror("pipe");
return -1;
}
pid = fork();
if(pid == -1)
{
perror("create fork");
return -1;
}
if(pid == 0)
{
//子進程,寫端,使用fd[1]
close(fd[0]);
//close(fd[1]);
while(1)
{
scanf("%s",buf);
if( write(fd[1],buf,strlen(buf)) == -1)
{
perror("write");
return -1;
}
memset(buf,0,20);
}
}
else
{
//父進程,讀端,使用fd[0]
close(fd[0]);
while(1)
{
}
}
return 0;
}
運行結果:
會出現管道破裂!!(如果沒有重寫管道破裂的處理函數,系統默認的處理方式就是殺死進程,父子進程都over了)
所以,總結一下讀寫規(guī)則:
讀規(guī)則:
1)緩沖區(qū)沒數據:阻塞
2)緩沖區(qū)的數據少于請求字節(jié)數:緩沖區(qū)有多少就讀多少
3)緩沖區(qū)的數據多于請求字節(jié)數:只讀取請求字節(jié)數,剩下的還在緩沖區(qū)
4)寫端關閉:讀端等待。
寫規(guī)則:
1)緩沖區(qū)滿了:寫不進去
2)沒有讀端:管道破裂,父子進程都結束了。調試到write,發(fā)生SIGPIPE。
注意:讀端和寫端的對應關系可以是一對一、一對多、多對一、多對多的。
上面講到,緩沖區(qū)如果滿了,就寫不進去了。那么緩沖區(qū)有多大呢?換言之,如何檢測linux中管道的容量?
代碼如下:
int main()
{
int fd[2];
pipe(fd);
char buf[4096]; //4k
int i,loop,ret;
for(i = 0 ; i < sizeof(buf) ; i++)
{
buf[i] = 'a';
}
loop = 100 ; //如果循環(huán)結束,還沒阻塞,增加循環(huán)次數
for(i = 0; i < loop ; i++)
{
ret = write(fd[1],buf,sizeof(buf));
if(ret == -1)
{
perror("write error!\n");
return 1;
}
else
{
printf("write successfully! ");
printf("size: %d K\n", (i+1)*4);
}
}
close(fd[0]);
close(fd[1]);
return 0;
}
運行結果:
在寫完64k的時候出現阻塞,說明管道已經滿了。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。