1、进程间的通信方式
a、管道通信:无名管道、有名管道
b、信号通信:包括信号的发送、接收和处理
c、IPC(Inter-Process Communication):共享内存、消息队列、信号灯
*** < 以上是单机模式下的进程通信,只有一个Linux内核 > ***
d、Socket通信:存在于一个网络中的两个进程间的通信(两个Linux内核)
2、管道文件、字符设备、块设备、套接字:只有文件节点,不占磁盘空间
普通文件、链接文件(软链接)、目录文件:不仅有inode号,还占磁盘空间
3、管道通信
A、无名管道
只能实现父子进程(亲缘关系)间通信
fork() 函数创建父子进程,库<sys/types.h>,子进程是对父进程的完全拷贝,包括管道的文件描述符
例:pid_t pid; pid = fork(); if(pid == 0){ } if(pid > 0){ }
pipe() 函数创建无名管道,库<unistd.h>,无名管道 没有文件名、打开方式和权限,只有两个文件描述符:fid[0] 读、fid[1] 写
(打开一个进程时,系统已自动创建了3个文件描述符:0、1、2,所以,fid从3开始计)
例:int fid[2]; int ret; ret = pipe(fid);
write(fid[1], &process_inter, sizeof(process_inter)); //写到哪里去、写什么、写多少个
read(fid[0], &process_inter, 4); //从哪里读、读到哪里去、读多少个
管道是创建在内存中的,进程结束,空间释放,管道就不存在了
管道中的内容读完了,就删除了(队列)
读阻塞:如果管道中没有东西可读又继续读,则会读阻塞
写阻塞:如果管道中写满了又继续写,则会写阻塞
B、有名管道
可实现非父子进程(非亲缘关系)间通信
mkfifo() 函数 创建管道文件节点
例:int ret; ret = mkfifo("./myfifo", 0777); 文件路径及文件名、权限模式
open() 函数 在内核创建管道空间
例:int fd; fd = open("./myfifo", O_WRONLY); 或 fd = open("./myfifo", O_RDONLY);
write(fd, &process_inter, sizeof(process_inter)); //写
read(fd, &process_inter, 1); //读
代码 - 父子进程 & 无名管道:
1 #include <stdio.h>
2 #include <sys/types.h> //进程 fork()
3 #include <unistd.h> //管道 pipe()
4
5 int main()
6 {
7 pid_t pid; //进程类型
8 int fid[2];
9 int ret;
10
11 int process_inter = 0;
12
13 ret = pipe(fid); //管道 先在内核空间创建管道,确保 父子进程 是操作同一个管道
14 if(ret < 0)
15 {
16 printf("pipe create failure.\n");
17 return -1;
18 }
19 printf("pipe create success. fid[0] = %d fid[1] = %d\n",fid[0],fid[1]);
20
21 pid = fork(); //父子进程
22 if(pid == 0) //子进程 对父进程 进行完全拷贝
23 {
24 int i = 0;
25 printf("***child process fid = %d\n",pid); //子进程号 为0
26 read(fid[0],&process_inter,4);
27 while(process_inter == 0);
28 while(i < 5)
29 {
30 printf("this is child proocess %d\n",i);
31 i++;
32 usleep(100);
33 }
34 }
35 if(pid > 0) //父进程
36 {
37 int i = 0;
38 printf("***parent process fid = %d\n",pid); //父进程号
39 for(i = 0; i < 5; i++)
40 {
41 printf("parent process %d\n",i);
42 usleep(90);
43 }
44 process_inter = 1;
45 write(fid[1],&process_inter,sizeof(process_inter));
46 //while(1);
47 }
48
49 return 0;
50 }
执行:父子进程 & 无名管道
代码:非亲缘进程 & 有名管道 -- 创建管道节点
1 #include <stdio.h>
2
3 int main()
4 {
5 int ret;
6 //管道文件、字符设备、块设备、套接字 只有文件节点,不占磁盘空间
7 ret = mkfifo("./myfifo",0777); //mkfifo()只是创建了管道文件节点,并没有在内核空间创建管道空间
8 //mkfifo()创建管道节点;open()在内核创建管道空间
9 if(ret < 0)
10 {
11 printf("myfifo create failure.\n");
12 return -1;
13 }
14
15 printf("myfifo create success.\n");
16 return 0;
17 }
1 #include <stdio.h>
2 #include <fcntl.h> //open()、read()、write()
3
4 int main()
5 {
6 int fd;
7 int i;
8 int process_inter = 0; //标识
9
10 //open()在内核创建管道空间
11 fd = open("./myfifo",O_WRONLY); //文件路径及文件名、权限模式
12 if(fd < 0)
13 {
14 printf("myfifo open failure.\n");
15 return -1;
16 }
17 printf("myfifo open success.\n");
18
19 for(i = 0; i < 5; i++)
20 {
21 printf("first process i = %d\n",i);
22 usleep(100);
23 }
24 process_inter = 1; //标识设为1
25 write(fd, &process_inter, sizeof(process_inter)); //写入管道。写到哪里去、写什么、写多少个
26 return 0;
27 }
代码:非亲缘进程 & 有名管道 -- 进程2
1 #include <stdio.h>
2 #include <fcntl.h> //open()、write()、read()
3
4 int main()
5 {
6 int fd;
7 int i;
8 char process_inter;
9
10 fd = open("./myfifo",O_RDONLY); //open():文件路径及文件名、权限模式
11 if(fd < 0)
12 {
13 printf("myfifo open failure.\n");
14 return -1;
15 }
16 printf("myfifo open success.\n");
17
18 read(fd, &process_inter, 1); //read()读取管道中的内容:从哪里读、都到哪里去、读多少个
19
20 while(process_inter == 0); //等待,直到 从管道中读取数值1
21
22 for(i = 0; i < 5; i++)
23 {
24 printf("this is second process i = %d\n",i);
25 usleep(100);
26 }
27 return 0;
28 }