linux-IPC -PIPE

进程间通信 (InterProcess Communication,IPC)


原因:由于不同进程地址空间也不同,A进程无法访问B进程的地址空间。任何一个进程的全局变量也无法被其他进程所见,因此,进程间通信必须通过内核。在内核中开辟一块缓冲区,A进程把数据从用户空间拷贝到内核缓冲区,B进程从内核缓冲区把数据读走,这便是IPC。

 


管道(PIPE)

1.PIPE是UNIX系统IPC最古老的形式,基本所有UNIX系统都支持这种机制。

2.历史上,PIPE是半双工的,现在某些系统提供了全双工PIPE,但是为了最佳的可移植性,我们不能假设系统支持全双工。

3.PIPE只能在具有血缘关系的两个进程之间使用。通常一个进程创建PIPE,fork之后的子进程和父进程之间就可以通过PIPE通信。

4.PIPE提供流式服务

5.PIPE生命周期和进程同步,进程结束则PIPE也消失了(即 匿名管道

6.内核会对PIPE进行同步互斥



#include <unistd.h>

int pipe(int fd[2]);
若成功,则返回0,若出错,则返回-1

fd[0]为读而打开

fd[1]为写而打开

因为管道是单向通信的,所以父子进程之间必须一个关闭读端,一个关闭写端。

如果管道的一端被关闭,则下面两条规则起作用:

1.当read一个写端已经被关闭的管道,在所有数据被读取之后,read返回0,表示文件结束。

2.如果write一个读端已被关闭的管道,则产生信号SIGPIPE。如果忽略该信号或者捕捉该信号并从其处理程序返回,则write返回-1,errno被设置为EPIPE。

在写管道时,常量PIPE_BUF规定了管道缓冲区的大小。如果对管道调用write,而且写的字节数小于或者等于PIPE_BUF,则此操作不会与其他进程对同一管道的write操作交叉进行。但是,若是有多个进程同时写一个管道,而且写的数据大于PIPE_BUF,那么我们所写的数据可能会和其他进程所写的数据相互交叉。

PIPE_BUF的值可以用pathconf或者fpathconf函数获取。


代码示例 :父进程写管道,子进程读管道

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main()
{
    int fd[2] = {0};
    pid_t pid;
    char msg[32] = {0};
    int nBytes = 0;

    pipe(fd);
    
    if ((pid = fork())<0){
        printf("fork error\n");
    }else if(pid>0){/*parent*/
        close(fd[0]);
        write(fd[1], "This is father\n", 32);
    }else{/*child*/
        close(fd[1]);
        nBytes = read(fd[0], msg, 32);
        if (nBytes>0)
            printf("child recv %s\n", msg);
    }
    exit(0);

}

函数popen和pclose

#include <stdio.h>

FILE *popen(const char *cmdstring, const char *type);
若成功,返回文件指针,若失败,返回NULL

int pclose(FILE *fp);
若成功,返回cmdstring的终止状态,若出错,返回-1

函数popen先执行fork,然后调用exec执行cmdstring,并且返回一个标准I/O文件指针。

如果type是“r”,则文件指针连接到cmdstring的标准输出;

如果type是“w”,则文件指针连接到cmdstring的标准输入。

cmdstring由BSHELL以下列方式执行:

sh -c cmdstring

可以使用:fp = popen("ls *.c", "r");


命名管道|有名管道(FIFO)


匿名管道只能在有血缘关系的进程之间传递数据,而有名管道可以在不相关的进程之间使用。

#include <sys/stat.h>

int mkfifo(const char *path, mode_t mode);

int mkfifoat(int fd, const char *path, mode_t mode);

若成功,返回0,若失败,返回-1

当我们创建FIFO时,都需要用open来打开它,正常的文件I/O函数如write read close unlink都需要FIFO。

当open一个FIFO时,非阻塞标志(O_NONBLOCK)会产生下列影响:

1.在一般情况下,只读open要阻塞到某个其他进程为写而打开这个FIFO为止。类似的,只写open要阻塞到某个其他进程为读而打开它为止。

2.如果指定了O_NONBLOCK,则只读open立即返回。但是,如果没有进程为读而打开一个FIFP,那么只写open将返回-1,并将errno设置为ENXIO。


参考书目《APUE》

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值