pipe 半双工_linux进程间通信之管道(无名管道pipe)实现全双工双向通信
管道是什么:
1. 管道只能用于具有親緣關(guān)系的進(jìn)程之間通信。
2.管道是一種單工或者說(shuō)半雙工的通信方式,傳遞信息的方向是固定的,只能由一端傳遞到另一端。
頭文件及函數(shù)原型:
#include
int pipe(int fd[2]);
當(dāng)用pipe 創(chuàng)建管道后,兩個(gè)文件描述符fd[0],fd[1]就可以使用了,其中fd[0]用于讀取,fd[1]用于寫(xiě)入。調(diào)用管道pipe返回值0表示成功,返回值-1表示失敗。
pipe函數(shù)創(chuàng)建管道后,接著fork出子進(jìn)程,子進(jìn)程繼承父進(jìn)程管道。
代碼舉例來(lái)看:
#include
#include
#include
#include
#include
#define MAX_DATA_LEN 256
#define DELAY_TIME 1
int main() {
pid_t pid;
char buf[MAX_DATA_LEN];
const char *data="Pipe Test";
int real_read,real_write;
int pipe_fd[2];
memset((void*)buf,0,sizeof(buf));
if(pipe(pipe_fd)<0){
perror("Pipe create error!\n");
exit(1);
}
if ((pid=fork())<0) {
perror("Fork error!\n");
exit(1);
} else if (pid==0) {
close(pipe_fd[1]);
sleep(DELAY_TIME*3);
if ((real_read=read(pipe_fd[0],buf,MAX_DATA_LEN))>0) {
printf("Child receive %d bytes from pipe: '%s'.\n",real_read,buf);
}
close(pipe_fd[0]);
exit(0);
} else {
close(pipe_fd[0]);
sleep(DELAY_TIME);
if ((real_write=write(pipe_fd[1],data,strlen(data)))>0) {
printf("Parent write %d bytes into pipe: '%s'.\n",real_write,data);
}
close(pipe_fd[1]);
waitpid(pid,NULL,0);
exit(0);
}
}
復(fù)制代碼
運(yùn)行輸出:
Parent write 9 bytes into pipe: 'Pipe Test'.
Child receive 9 bytes from pipe: 'Pipe Test'.
上述代碼只能從父進(jìn)程向子進(jìn)程傳遞,如何從子進(jìn)程向父進(jìn)程傳遞呢?我們看到父進(jìn)程關(guān)閉了管道讀取端“close(pipe_fd[0]);”,子進(jìn)程關(guān)閉了管道寫(xiě)入端“close(pipe_fd[1]);”,如果取消關(guān)閉這兩個(gè)端,是否能夠?qū)崿F(xiàn)子進(jìn)程向父進(jìn)程傳遞呢。
父進(jìn)程先發(fā)送,子進(jìn)程接收,然后子進(jìn)程再發(fā)送,父進(jìn)程再接收,實(shí)現(xiàn)全雙工互相通信,期望運(yùn)行結(jié)果如下:
Parent write 9 bytes into pipe: 'Pipe Test'.
Child receive 9 bytes from pipe: 'Pipe Test'.
Child write 9 bytes from pipe: 'Pipe Test'.
Parent receive 9 bytes from pipe: 'Pipe Test'.
修改代碼如下:
#include
#include
#include
#include
#include
#define MAX_DATA_LEN 256
#define DELAY_TIME 1
int main() {
pid_t pid;
char buf[MAX_DATA_LEN];
const char *data="Pipe Test";
int real_read,real_write;
int pipe_fd[2];
memset((void*)buf,0,sizeof(buf));
if(pipe(pipe_fd)<0){
perror("Pipe create error!\n");
exit(1);
}
if ((pid=fork())<0) {
perror("Fork error!\n");
exit(1);
} else if (pid==0) {
//close(pipe_fd[1]);
sleep(DELAY_TIME*3);
if ((real_read=read(pipe_fd[0],buf,MAX_DATA_LEN))>0) {
printf("Child receive %d bytes from pipe: '%s'.\n",real_read,buf);
}
if ((real_write=write(pipe_fd[1],data,strlen(data)))>0) {
printf("Child write %d bytes into pipe: '%s'.\n",real_write,data);
}
close(pipe_fd[0]);
exit(0);
} else {
//close(pipe_fd[0]);
sleep(DELAY_TIME);
if ((real_write=write(pipe_fd[1],data,strlen(data)))>0) {
printf("Parent write %d bytes into pipe: '%s'.\n",real_write,data);
}
if ((real_read=read(pipe_fd[0],buf,MAX_DATA_LEN))>0) {
printf("Parent receive %d bytes from pipe: '%s'.\n",real_read,buf);
}
close(pipe_fd[1]);
waitpid(pid,NULL,0);
exit(0);
}
}
復(fù)制代碼
但是實(shí)際運(yùn)行如下:
Parent write 9 bytes into pipe: 'Pipe Test'.
Parent receive 9 bytes from pipe: 'Pipe Test'.
可以看到,父進(jìn)程發(fā)送的數(shù)據(jù)被父進(jìn)程自己接收了,子進(jìn)程讀不到數(shù)據(jù)被阻塞了。顯然這種方法不行。
因?yàn)楣艿朗菃喂さ?#xff0c;只能固定從一個(gè)方向傳遞到另一個(gè)方向。
要實(shí)現(xiàn)互相通信,一個(gè)管道是不行的,可以創(chuàng)建兩個(gè)管道,一個(gè)管道是父寫(xiě)子讀,另一個(gè)是子寫(xiě)父讀。
代碼如下:
#include
#include
#include
#include
#include
#define MAX_DATA_LEN 256
#define DELAY_TIME 1
int main() {
pid_t pid;
char buf[MAX_DATA_LEN];
const char *data="Pipe Test";
int real_read,real_write;
int pipe_fd[2],pipe_fd2[2];
memset((void*)buf,0,sizeof(buf));
if(pipe(pipe_fd)<0){
perror("Pipe create error!\n");
exit(1);
}
if(pipe(pipe_fd2)<0){
perror("Pipe create error!\n");
exit(1);
}
if ((pid=fork())<0) {
perror("Fork error!\n");
exit(1);
} else if (pid==0) {
close(pipe_fd[1]);
close(pipe_fd2[0]);
sleep(DELAY_TIME*3);
if ((real_read=read(pipe_fd[0],buf,MAX_DATA_LEN))>0) {
printf("Child receive %d bytes from pipe: '%s'.\n",real_read,buf);
}
if ((real_write=write(pipe_fd2[1],data,strlen(data)))>0) {
printf("Child write %d bytes into pipe: '%s'.\n",real_write,data);
}
close(pipe_fd[0]);
close(pipe_fd2[1]);
exit(0);
} else {
close(pipe_fd[0]);
close(pipe_fd2[1]);
sleep(DELAY_TIME);
if ((real_write=write(pipe_fd[1],data,strlen(data)))>0) {
printf("Parent write %d bytes into pipe: '%s'.\n",real_write,data);
}
if ((real_read=read(pipe_fd2[0],buf,MAX_DATA_LEN))>0) {
printf("Parent??receive %d bytes from pipe: '%s'.\n",real_read,buf);
}
close(pipe_fd[1]);
close(pipe_fd2[0]);
waitpid(pid,NULL,0);
exit(0);
}
}
復(fù)制代碼
運(yùn)行結(jié)果:
Parent write 9 bytes into pipe: 'Pipe Test'.
Child receive 9 bytes from pipe: 'Pipe Test'.
Child write 9 bytes into pipe: 'Pipe Test'.
Parent??receive 9 bytes from pipe: 'Pipe Test'.
可以看到,創(chuàng)建了兩個(gè)管道 “int pipe_fd[2],pipe_fd2[2];”,
pipe_fd 是父寫(xiě)子讀,pipe_fd2是子寫(xiě)父讀,通過(guò)兩個(gè)管道,實(shí)現(xiàn)了進(jìn)程的全雙工互相通信。
總結(jié)
以上是生活随笔為你收集整理的pipe 半双工_linux进程间通信之管道(无名管道pipe)实现全双工双向通信的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java 定义16进制_java数据类型
- 下一篇: 金钏跳井,凸显贾府主子冷血,下人们离心离