六、进程间通信-有名管道
命名管道
可用于没有亲缘关系的进程间进行数据传输,数据只能单向流动。
(1)创建管道
#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文件,父进程读取文件数据
#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; }