六、进程间通信-有名管道
命名管道
可用于没有亲缘关系的进程间进行数据传输,数据只能单向流动。
(1)创建管道
1 2 3 4 | #include <sys/types.h> #include <sys/stat.h> int mkfifo( const char *filename,mode_t mode) |
-
filename:用户读写的FIFO文件名。
mode:模式及权限参数说明:
-
O_RDONLY:只读管道。
-
O_WRONLY:只写管道
-
O_RDWR:读写管道。
-
O_NONBLOCK:非阻塞。
-
O_CREAT:如果该fifo文件不存在,那么就创建一个新的文件,并用第三个参数为其设置权限。
-
O_EXCL:如果使用O_CREAT时文件存在,那么可返回错误信息。这一参数可测试文件是否存在。
-
0:成功
-
EACCESS:参数filename所指定的目录路径五可执行的权限。
-
EEXIST:参数filename所指定的文件已存在。
-
ENAMETOOLONG:参数filename的路径名称太长。
-
ENOENT:参数filename包含的目录不存在。
-
ENOSPC:文件系统的剩余空间不足。
-
ENOTDIR:参数filename路径种的目录存在但却非真正的目录。
-
EROFS:参数filename指定的文件存在于只读文件系统内。
(2)特点
-
任意进程间数据传输
-
write和read操作可能会阻塞进程
-
write具有"原子性"
- 使用FIFO的过程中,当一个进程对管道进行读操作时:
-
若该管道是阻塞类型,且当前FIFO内没有数据,则对读进程而言将一直阻塞到有数据写入。
-
若该管道是非阻塞类型,则不论FIFO内是否有数据,读进程都会立即执行读操作。即如果FIFO内没有数据,读函数将立即返回0.
-
- 使用FIFO的过程中,当一个进程对管道进行写操作时:
-
若该管道是阻塞类型,则写操作将一直阻塞到数据可以被写入。
-
若该管道是非阻塞类型而不能写入全部数据,则写操作进行部分写入或者调用失败。
-
(3)使用步骤
- 第一个进程mkfifo有名管道
- open有名管道,write/read数据
- close有名管道
- 第二个进程open有名管道,read/write数据
- close有名管道
(4)实例
子进程写数据到FIFO文件,父进程读取文件数据
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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <limits.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <errno.h> #define MAX_BUFFER_SIZE PIPE_BUF /*大小为4096,定义在limits.h种*/ #define MYFIFO "myfifo" void fifo_read( void ) { char buff[MAX_BUFFER_SIZE]; int fd; int nread; printf ( "********************read fifo***********************\n" ); if (access(MYFIFO,F_OK) == -1) { if ((mkfifo(MYFIFO,0666) <0)&&( errno !=EEXIST)) { printf ( "Cannot create FIFO file\n" ); exit (1); } } fd = open(MYFIFO,O_RDONLY); if (fd == -1) { printf ( "open fifo file error\n" ); exit (1); //exit(1)表示异常退出.这个1是返回给操作系统的,0表示正常退出。 } memset (buff,0,MAX_BUFFER_SIZE); if ((nread = read(fd,buff,MAX_BUFFER_SIZE)) > 0) { printf ( "Read '%s' from FIFO\n" ,buff); } printf ( "********************close fifo******************************\n" ); close(fd); exit (0); } void fifo_write( void ) { int fd; char buff[] = "this is a fifo test demo" ; int nwrite; sleep(2); //等待子进程先运行 /*以只写阻塞方式打开FIFO管道*/ fd = open(MYFIFO,O_WRONLY|O_CREAT,0644); if (fd == -1) { printf ( "Open fifo file error\n" ); exit (1); } printf ( "Write '%s' to FIFO\n" ,buff); /*向管道中写入字符串*/ nwrite = write(fd,buff,MAX_BUFFER_SIZE); if (wait(NULL)) //等待子进程退出 { close(fd); exit (0); } } int main() { pid_t result; result = fork(); if (result == -1) { printf ( "Fork error\n" ); } else if (result == 0) //子进程 { fifo_read(); } else //父进程 { fifo_write(); } return result; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)