现在Linux进程间通信方式包括:无名管道(pipe)及有名管道(fifo)、信号(signal)、消息队列(message queue)、共享内存(shared memory)、信号量(semaphore)、套接字(socket)
管道:把一个程序的输出直接连接到另一个程序的输入。
无名管道
(1)只能用于具有亲缘关系的进程之间的通信(父进程和子进程之间)
(2)单工通信模式,固定读端和写端
(3)特殊的文件,可以使用普通的read()、write()等函数,不属于文件系统,只存在于系统中
创建与关闭——pipe()、close()
头文件;#include <unistd.h>
函数原型:int pipe(int fd []);
fd:包含两个元素的整型数组,存放管道对于文件描述符
成功:0
失败:-1
创建管道
1
2
3
4
5
6
7
8
9
10
11
12
13#include <stdio.h> #include <unistd.h> #include <stdlib.h> int main() { int pfd[2]; int ret=pipe(pfd); if(ret<0) { perror("fail to pipe"); exit(-1); } }
无名管道是基于文件描述符的通信方式。当一个管道建立时,他会创造两个文件描述符:fd[0]--读端、fd[1]--写端
管道关闭时只需要用close()函数将两个文件描述符关闭
示例:首先创建管道,然后父进程使用fork()函数创建子进程,最后通过关闭父进程的读描述符和子进程的写描述符,建立它们之间的管道通信
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <stdlib.h> #include <errno.h> //? #include <sys/wait.h> #include <string.h> #define MAX_DATA_LEN 256 #define DELAY_TIME 1 int main() { pid_t pid; int pipe_fd[2]; char buf[MAX_DATA_LEN]; const char data[]="Pipe Test Program"; int real_read,real_write; memset(buf,0,sizeof(buf)); if(pipe(pipe_fd[2])<0) //创建管道 { perror("fail to pipe"); exit(-1); } if((pid=fork())==0) //创建子进程 { close(pipe_fd[1]); //子进程关闭写描述符 sleep(DELAY_TIME); //通过暂停1s等待父程序关闭相应的读描述符 if((real_read=read(pipe_fd[0],buf,MAX_DATA_LEN))>0) //子进程读取管道内内容到buf里 { printf("%d bytes read from the pipe is '%s'n",real_read,buf); } close(pipe_fd[0]); //关闭子程序读描写符 exit(0); } else if(pid>0) { close(pipe_fd[0]); //关闭父进程读描述符 if((real_write=write(pipe_fd[1],data,strlen(data)))!=-1) { printf(""parent wrote %d bytes:'%s'n",real_write,data); } close(pipe_fd[1]); //关闭父进程写描述符 wait(pid,NULL,0); //收集子进程退出信息 exit(0); } }
有名管道
创建管道——mkfifo()
头文件:
#include <sys/types.h>
#include <sys/state.h>
函数原型:int mkfifo(const char *filename, mode_t mode)
filename:要创建的管道名
mode:管道的访问权限
成功:0
失败:-1
创建成功后可以使用open()、read()、write()。对于为读而打开的管道可在open()中设置O_RDONLY,对于为写而打开的管道可在open()中设置O_WRONLY。
示例:示例包含两个程序,一个用于读管道,另一个用于写管道。在读管道的程序里创建管道,并且作为main()函数里的参数由用户输入要写入的内容。读管道的程序会读出用户写入管道的内容。
写管道:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <fcntl.h> #include <string.h> #define MYFIFO "/tmp/myfifo" //有名管道文件名 int main(int argc,char *argv[]) { int fd; int nwrite; if(argv<2) { printf("Usage:./fifo_write stringn"); exit(-1); } if((fd=open(MYFIFO,O_WRONLY))<0) //以只写方式打开FIFO管道 { perror("fail to open fifo"); exit(-1); } if((nwrite=write(fd,argv[1],strlen(argv[1])+1))>0) //向管道中写入字符串 { printf("Write '%s' to FIFOn",argv[1]); } close(fd); return 0; }
读管道:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <fcntl.h> #include <string.h> #define MYFIFO "/tmp/myfifo" //有名管道文件名 int main() { char buf[256]; int fd; //判断有名管道是否已存在,若尚未建立,则以相应的权限创建 if(access(MYFIFO,F_OK)==-1) //管道不存在 { if(mkfifo(MYFIFO,O666)<0) { perror("fail to mkfifo"); exit(-1); } } //以只读的方式打开有名管道 if((fd=open(MYFIFO,O_RDONLY))<0) { perror("fail to open fifo"); exit(-1); } while(1) { memset(buf,0,sizeof(buf)); //? if((nread=read(fd,buf,256))>0) { printf("Read '%s' from FIFOn",buf); } } close(fd); return 0; }
最后
以上就是优雅毛巾最近收集整理的关于【Linux】管道通信的全部内容,更多相关【Linux】管道通信内容请搜索靠谱客的其他文章。
发表评论 取消回复