IPC(Inter Process Connection) 总结笔记(1)

来源:互联网 发布:知柏地黄丸与难入睡 编辑:程序博客网 时间:2024/04/30 15:50

管道(PIPE)

管道的创建和使用流程

  • 管道本身是一种文件(linux 一切皆文件),由于其特殊性,它的创建函数被封装 pipe(int fd[2]),不同于linux下普通文件的创建(create(path,mode)

  • 管道的数据传输,是单向的,从fd[1]—–>fd[0],所以,在fd[1]这个文件描述符端,执行写操作 write(fd[1],buff,strllen(buff)+1);相应的,在fd[0]端执行读操作read(fd[0],buff,100)(100是buff定义时的长度)

  • 管道只用于父子进程间的通讯,子写父读,或父读子写
  • 在执行读写操作之前,把管道另一端的文件关闭,即先执行 close()再执行read()/write()

全双工管道

创建两个普通管道,但读写端是这样设定的:

  • 一进程先读后才,另一进程必须先写后读
  • 两进程都可先写后读,但不可同时先读后写,不然父子进程都同时阻塞

注意

  • 子进程,在进程的一开始处,如果子进程调用 exec 族函数 执行另外一个程序时,子进程不再共享父进程的文件描述符,linux提供 dup(int oldfd) 将子进程的文件描述符重定位到stdin (在执行该函数之前,为确保重定向标准输入即fd=0,得先执行close(0)),执行的新程序,从标准输入读入父进程传递的数据 read(stdin,buf,bufsize)

  • 管道本身具有一个缓冲区,并且它的大小在include/linux/limits.h被宏定义尾PIPE_BUF.在执行write(fd[0]),buf,bufsize)时:

    PIPE_BUF
    POSIX.1-2001 says that write(2)s of less than PIPE_BUF bytes must be atomic: the output data is written to the pipe as a contiguous
    sequence. Writes of more than PIPE_BUF bytes may be nonatomic: the kernel may interleave the data with data written by other processes. POSIX.1-2001 requires PIPE_BUF to be at least 512 bytes. (On Linux,PIPE_BUF is 4096 bytes.) The precise semantics depend on whether the file descriptor is nonblocking (O_NONBLOCK), whether there are multiple writers to the pipe, and on n, the number of bytes to be written:

总结起来:

  • O_NONBLOCK disabled, n <= PIPE_BUF,All n bytes are written atomically; write(2) may block if there is not room for n bytes to be written immediately

    阻塞模式时且n < PIPE_BUF:写入具有原子性,如果没有足够的空间供n个字节全部写入,则阻塞直到有足够空间将n个字节全部写入管道

  • O_NONBLOCK enabled, n <= PIPE_BUF, If there is room to write n bytes to the pipe, then write(2) succeeds immediately, writing all n bytes; otherwise write(2) fails, with errno set to EAGAIN.

    非阻塞模式时且n < PIPE_BUF:写入具有原子性,立即全部成功写入,否则一个都不写入,返回错误

  • O_NONBLOCK disabled, n > PIPE_BUF The write is nonatomic: the data given to write(2) may be interleaved with write(2)s by other process; the write(2) blocks until n bytes have been written.

    阻塞模式时且n > PIPE_BUF:不具有原子性,可能中间有其他进程穿插写入,直到将n字节全部写入才返回,否则阻塞等待写入

  • O_NONBLOCK enabled, n > PIPE_BUF If the pipe is full, then write(2) fails, with errno set to EAGAIN. Otherwise, from 1 to n bytes may be written (i.e., a “partial write” may occur; the caller should check the return value from write(2) to see how many bytes were actually written), and these bytes may be interleaved with writes by other processes.

    非阻塞模式时且N > PIPE_BUF:如果管道满的,则立即失败,一个都不写入,返回错误,如果不满,则返回写入的字节数为1~n,即部分写入,写入时可能有其他进程穿插写入

    • 当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性
    • 当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性

命名管道(named pipe/FIFO)

为啥引入有名管道?

  • 首先解决不相关进程间的通信问题;
  • 其次FIFO是存在与磁盘上的文件(管道是在内存),这提供了一个路径名与之关联。进程只要知道该文件的路径,就能访问该文件,通过该文件进行通讯;
  • 有名管道按先进先出的原则工作,第一个写入的数据首先被读出。

有名管道如何进行通讯

1.创建有名管道

#include <sys/types.h>#include <sys/stat.h>int mknode (const char* path,mode_t mode | S_IFIFO,(dev_t)0);int mkfifo(const char *filename, mode_t mode);

mode 是读写权限
例如创建一个FIFO

...#define deal_with_err(error_message) \do{\perror(error_message); \exit(1); \}while(0)...umask(0);if(mkfifo("/tmp/fifo",S_IFIFO |0666)==-1){   deal_with_error("create FIOF fail");}// use mkfifo more frequently at your best/* if(mknod("/tmp/fifo",S_IFIFO | 0666,0) == -1) {    deal_with_error("create FIOF fail"); } */

2.打开管道

open(const char *path, O_RDONLY);//1open(const char *path, O_RDONLY | O_NONBLOCK);//2open(const char *path, O_WRONLY);//3open(const char *path, O_WRONLY | O_NONBLOCK);//4

阻塞/非阻塞

3.读写操作

  • 如果进行全双工通讯,注意read(),write()顺序的安排
0 0
原创粉丝点击