进程间通信

进程间通信的本质就是让不同的进程看到同一份资源,也就是同一块内存

进程间通信的目的

  • 数据传输
  • 资源共享
  • 通知事件
  • 进程控制

进程通信分离

  • 管道
    • 匿名管道pipe
    • 命名管道
  • System V IPC
    • 消息队列
    • 共享内存
    • 信号量
  • POSIX IPC
    • 消息队列
    • 共享内存
    • 信号量
    • 互斥量
    • 条件变量
    • 读写锁

管道

管道都是单向传输内容的 

匿名管道

父进程写入,子进程读

#include <unistd.h>
int pipe(int fd[2]);
// 创建一个无名管道,fd[0]表示读端,fd[1]表示写端
// 成功返回0,失败返回错误代码

父进程创建管道,然后fork出子进程,父进程关闭fd[0],子进程关闭fd[1]。

管道的特点:

  1. 管道是用来进行具有血缘关系的进程进行进程间通信
  2. 管道具有通过进程间协同,提供了访问控制
  3. 管道提供的是面向流的通信服务
  4. 管道是基于文件的,文件的生命周期是随进程的,管道的生命周期也是随进程的
  5. 管道是单向通信

访问控制:

  1. 写快读慢,写满了就不能再写
  2. 写慢读块,管道没有数据的时候,读需要等待
  3. 写关,没有读,就读到文件结尾
  4. 读关,写继续,OS终止写进程

例子:从键盘读取数据,写入管道,读取管道,写到屏幕

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main( void )
{
    int fds[2];
    char buf[100];
    int len;
    if ( pipe(fds) == -1 )
        perror("make pipe"),exit(1);
    // read from stdin
    while ( fgets(buf, 100, stdin) )    
    {
        len = strlen(buf);
        // write into pipe
        if ( write(fds[1], buf, len) != len ) {
            perror("write to pipe");
            break;
        }
        memset(buf, 0x00, sizeof(buf));
        // read from pipe
        if ( (len=read(fds[0], buf, 100)) == -1 ) {
            perror("read from pipe");
            break;
        }
        // write to stdout
        if ( write(1, buf, len) != len ) {
            perror("write to stdout");
            break;
        }
    }
}

命名管道

在不相关的进程之间交换数据,可以使用FIFO文件。命名管道就是一种特殊的文件

// 创建命名管道
int main(int argc, char *argv[])
{
    mkfifo("p2", 0644);
    return 0;
}
// 函数原型:int mkfifo(const char *filename,mode_t mode);

区别

唯一的区别就是在创建与打开的方式不同。命名管道由mkfifo创建,open打开;匿名管道由pipe创建并打开。

共享内存

 提供者是操作系统,共享内存=共享内存块+对应的共享内存的内核数据结构来管理

当进程结束时,共享内存块还在。system v的ipc资源,生命周期随内核,需要自己删除

ipcs -m // 查看共享内存
ipcrm -m id // 删除id的共享内存

共享是属于用户空间,就是不用经过系统调用,直接可以访问。双方进程如果想通信,直接机械能内存级的读写就可。共享内存是最快的,因为不需要拷贝,也就不用交给操作系统;但是缺乏访问控制,会带来并发问题。

信号量

让不同的进程看到了同一份资源,也带来了一些时序问题,造成数据不一致问题

临界资源:多个进程(执行流)看到的公共的一份资源

临界区:自己的进程,访问临界资源的代码

互斥:为了更好的进行临界区的保护,可以让多执行流在任何时刻都只能一个进程进入临界区

原子系:要么不做,要么做完,没有中间状态

所以多个执行流,运行的时候互相干扰,主要是我们不加保护的访问了同样的资源(临界资源),在非临界区多个执行流互相是不影响的

申请信号量的本质:让信号量计数器--,P操作,必须是原子的

申请信号量成功,临界资源内部,一定会给你预留你想要的资源,本质就是临界资源的一种预定机制

释放信号量就是计数器++,V操作,必须是原子的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值