管道是一种文件,
无名管道:
1)没有名字的文件,没有在磁盘里面形成具体的文件
2)不能用lseek定位
3)退出程序后,程序内部的管道资源会被释放,下次运行需要在创建,才能使用
4)只能用在亲缘进程(父子,爷孙,兄弟)
5)pipe实在fork之前创建的(4个读写端口,两个读两个写,才能够实现亲缘进程双向通信)
6)无名管道是在内核空间创建出来的。
7)半双工通信(读端只能读,不能写)
8)无名管道不能用open打开
9)写操作没有原子性。(不能给他一个多进程的环境,只能进程单一的通信)
原子性(多线程操作,全局共享区:数据):一旦任务(代码—任务函数)启动,一定要做完才能做其他事情(不能打断他,不能影响他)
无名管道的API
创建一条无名管道并且给你两个文件描述符(读写的文件描述符)
pipefd[0]:读端
pipefd[1]:写端
1)创建管道
2)创建进程
3)关闭管道
示例代码:
#include <stdio.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <sys/wait.h> #include <sys/types.h> #include <unistd.h> int main() { int pipefd[2] = {0}; pipe(pipefd); //创建无名管道 pid_t ret = fork(); //创建进程 if (ret == -1) { perror("fork"); } else if (ret == 0) { char msg_data[32] = {0}; memset(msg_data, 0, 32); printf("请输入发给父亲的信息:"); scanf("%s", msg_data); write(pipefd[1], msg_data, strlen(msg_data)); exit(0); } else { char msg_data[32]; memset(msg_data, 0, 32); read(pipefd[0], msg_data, 32); printf("儿子说:%s\n", msg_data); wait(NULL); } //关闭管道文件 close(pipefd[0]); close(pipefd[1]); return 0;
有名管道:
有名字的管道,所有具体的文件,存放在闪存里面。
特点:
1)血缘与非血缘都可以用
2)可用open打开(才有文件描述符)
3)不能用lseek定位
4)写操作具有原子性。
5)全双工(一个管道只有一个文件描述符:读和写)
6)退出程序后,有名管道可以一直使用,直到你把管道文件删掉。 (rx xxx)
有名管道的API
代码思路:
1)第一步:
判断管道文件存不存在 — access();
access:可以判断文件是否存在,可读,可写,可执行 #include <unistd.h> /tmp/dante_fifo F_OK int access(const char *pathname, int mode); pathname:文件的路径 mode:功能选项 R_OK W_OK X_OK F_OK: 文件存不存在
存在:进入第三步
不存在则进入第二步
2)第二步:
创建管道文件,进入第三步
3)第三步:
直接打开
4)第四步:
调用
read
write
发送和接收信息
5)第五步:
close 关闭管道
示例代码:
小明发送信息给小红
#include <stdio.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #define PATH "/tmp/fifo" int main() { if(access(PATH, F_OK)) { umask(0000); //创建管道文件 mkfifo(PATH, 0777); } //打开管道文件 int fd = open(PATH, O_RDWR); if(fd == -1) { perror("open failed"); exit(-1); } char msg_data[10]; while(1) { memset(msg_data,0,10); printf("发给小红的信息:"); scanf("%s", msg_data); write(fd, msg_data, strlen(msg_data)); } close(fd); return 0; }
小红接收到小明信息
#include <stdio.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #define PATH "/tmp/fifo" int main() { if(access(PATH, F_OK)) { umask(0000); //创建管道文件 mkfifo(PATH, 0777); } //打开管道文件 int fd = open(PATH, O_RDWR); if(fd == -1) { perror("open failed"); exit(-1); } char msg_data[10]; while(1) { memset(msg_data,0,10); printf("小红接收到小明的信息:"); read(fd, msg_data, 10); printf("%s\n", msg_data); } close(fd); return 0; }
.
代码实现效果: