Fork() 函数:
返回0时是子进程,否则,是父进程。
pipe函数
int pipe(int filedes[2]);
返回值:成功,返回0,否则返回-1。参数数组包含pipe使用的两个文件的描述符。fd[0]:读管道,fd[1]:写管道。
必须在fork()中调用pipe(),否则子进程不会继承文件描述符。两个进程不共享祖先进程,就不能使用pipe。但是可以使用命名管道。
当管道进行写入操作的时候,如果写入的数据小于128K则是非原子的,如果大于128K字节,缓冲区的数据将被连续地写入
管道,直到全部数据写完为止,如果没有进程读取数据,则将一直阻塞
命名管道FIFO
管道最大的劣势就是没有名字,只能用于有一个共同祖先进程的各个进程之间。FIFO代表先进先出,单它是一个单向数据流,也就是半双工,和
管道不同的是:每个FIFO都有一个路径与之关联,从而允许无亲缘关系的进程访问。
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
这里pathname是路径名,mode是sys/stat.h里面定义的创建文件的权限.
以下示例程序来自:http://blog.chinaunix.net/uid-20498361-id-1940238.html
从例子上可以看出使用fifo时需要注意:
*fifo管道是先调用mkfifo创建,然后再用open打开得到fd来使用.
*在打开fifo时要注意,它是半双工的的,一般不能使用O_RDWR打开,而只能用只读或只写打开.
fifo可以用在非亲缘关系的进程间,而它的真正用途是在服务器和客户端之间. 由于它是半双工的所以,如果要进行客户端和服务器双方的通信的话,
每个方向都必须建立两个管道,一个用于读,一个用于写.
read函数
用于文件描述符对应的文件中读取数据,原型:
ssize_t read(int fd,void*buf,size_t count)
参数说明:
fd: 是文件描述符, 从command line获取数据时,为0
buf: 为读出数据的缓冲区;
count: 为每次读取的字节数(是请求读取的字节数,读上来的数据保
存在缓冲区buf中,同时文件的当前读写位置向后移)
返回值:
成功:返回读出的字节数
失败:返回-1,并设置errno,如果在调用read
之前到达文件末尾,则这次read返回0
write函数
用于将数据写入到文件描述符对应的文件,原型:
ssize_t write(int fd,const void*buf,size_t count);
参数说明:
fd:是文件描述符(输出到command line,就是1)
buf:通常是一个字符串,需要写入的字符串
count:是每次写入的字节数
返回值:
成功:返回写入的字节数
失败:返回-1并设置errno
ps: 写常规文件时,write的返回值通常等于请求写的字节
数count, 而向终端设备或者网络写时则不一定
实例:
以下程序再提供全双工管道的系统下,能够看到
child read p
parent read c
再默认提供半双工管道的系统下,则会出错。
#include "unpipc.h"int main(int argc,char **argv){int fd[2],n;char c;pid_t childpid;Pipe(fd);if((childpid = Fork()) == 0){sleep(3);printf("sleep over !\n");if((n = Read(fd[0],&c,1))!=1){printf("read err \n");err_quit("child: read returned %d",n);}printf("child test \n");printf("child read %c\n",c);Write(fd[0],"d",1);//exit(0);}printf("parent do \n");Write(fd[1],"p",1);printf("parent write over ! \n");sleep(4);if((n = Read(fd[1],&c,1))!=1){printf("parent read error ! \n");err_quit("parent: read returned %d",n);}printf("parent read %c\n",c);exit(0);
}
参考:
https://www.cnblogs.com/kunhu/p/3608109.html
https://blog.csdn.net/IOT2017/article/details/84137728