在linux中使用的进程间通信(IPC)方法有
1、管道(pipe)和有名管道(FIFO)
2、信号(signal)
3、消息队列
4、共享内存
5、信号量
6、套接字
下面介绍管道的用法:
管道是单向的、先进先出的,它把一个进程的输出和另一个进程的输入连接在一起,一个进程(写进程)往管道尾部写入数据,另一个进程(读进程)在管道首部读取数据。
当管道中的数据被读取时,管道中的这个数据会被删除,当进程读取空管道时会发生阻塞,同理当进程往满管道里写入数据时也会阻塞。
管道分为两类,无名管道(pipe)和有名管道(FIFO),前者用于子进程和父进程之间的通讯,后者用于不同进程之间的通讯。
无名管道的创建使用的是 pipe函数,pipe函数的原型:
int pipe(int filedis[2]);
filedis是一个数组,它含有两个文件描述符,filedis[0]用于读,fileids[1]用于写。
管道使用后是需要关闭的,而管道的关闭只需要使用close函数关闭那两个文件描述符即可。
在创建无名管道时,必须在创建子进程之前创建无名管道,这样子进程才会继承父进程的管道。
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <unistd.h>
4 #include <errno.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <sys/wait.h>
8
9 int main(int argc, char **argv)
10 {
11 int pipe_fd[2]; //创建pipe的文件描述符
12 char buf[100];
13 pid_t pid;
14
15 memset(buf,0,sizeof(buf));
16
17 if (pipe(pipe_fd)<0) { //创建pipe
18 printf("can not create pipe");
19 exit(1);
20 }
21
22 pid = fork(); //创建子进程
23
24 if (pid == 0) {
25 close(pipe_fd[0]);
26 if (write(pipe_fd[1],"test 123456\n",16)<0) { //往pipe中写入数据
27 printf("pipe can not write\n");
28 exit(1);
29 }
30 else {
31 printf("test success\n");
32 }
33 close(pipe_fd[1]);
34
35 }
36 else if (pid > 0) {
37 close(pipe_fd[1]);
38 sleep(2);
39 wait(NULL); //等待子进程运行完毕
40 if (read(pipe_fd[0],buf,100)<0) { //从pipe中读取数据
41 printf("can not read\n");
42 exit(1);
43 }
44 else {
45 printf("read %s from pipe\n",buf);
46 }
47 close(pipe_fd[0]);
48 }
49
50 return 0;
51 }
有名管道用于不同进程之间的通讯,因此需要创建两个函数,一个fifo_read.c,一个fifo_write.c,在fifo_read.c中创建fifo。
fifo_read.c
1 #include <unistd.h>
2 #include <sys/wait.h>
3 #include <sys/types.h>
4 #include <errno.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8
9
10 int main(int argc, char **argv)
11 {
12 int fd;
13 char buf_r[100];
14 int acc;
15
16 memset(buf_r,0,sizeof(buf_r));
17 if ((acc=access(FIFO,F_OK))==-1) { //判断FIFO文件是否已创建
18 if (mkfifo(FIFO,0777) < 0) { //创建FIFO文件
19 printf("fifo can not create\n");
20 exit(1);
21 }
22 }
23 printf("acc = %d\n",acc);
24
25 printf("read byte......\n");
26 fd = open(FIFO,O_RDONLY | O_NONBLOCK,0); //打开FIFO文件
27 printf("open\n"); //测试
28 if (fd == -1) {
29 printf("can not open fifo\n");
30 }
31 printf("while\n");
32 while (1) {
33 memset(buf_r,0,sizeof(buf_r));
34 if (read(fd,buf_r,100) == 0) { //读数据
35 printf("no data\n");
36 }
37
38 printf("read %s from fifo\n",buf_r);
39 sleep(2);
40 }
41 pause();
42 return 0;
43 }
fifo_write.c
1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>
4 #include <unistd.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #define FIFO "/home/book/c/fifo/myfifo"
9
10 int main(int argc ,char **argv)
11 {
12 int fd;
13
14 fd = open(FIFO,O_WRONLY | O_NONBLOCK,0);
15 if (fd == -1) {
16 printf("can not open fifo\n");
17 exit(1);
18 }
19 if (write(fd,"hello linux", 14)<0) {
20 printf("write error\n");
21 exit(1);
22 }
23 else {
24 printf("write succse\n");
25 }
26
27 return 0;
28 }
开打两个命令窗口分别运行读函数和写函数
在使用有名管道时,出现了无法创建FIFO的问题,在排查后发现,由于FIFO文件只能创建一次,当第二次运行fifo_read时,FIFO文件已存在,程序就会出错退出,因此我使用了access函数来判断FIFO文件是否已创建。
出现O_RDONLY未定义等问题,可添加头文件
#include <sys/stat.h>
#include <fcntl.h>