进程间通信

IPC: Inter Processes Communication

  • 进程是一个独立的资源分配单位,不同进程(用户进程)的资源是独立的,没有关联,不能在一个进程中直接访问另一个进程的资源。
  • 但是进程不是孤立的,不同的进程需要进行信息的交互和状态的传递等,因此需要进程间通信

进程间通信的目的

  • 数据传输:一个进程需要将他的数据发送给另一个进程
  • 通知事件:一个进程需要向另一个或一组进程发送消息,通知他们发生了某种事件(如进程终止时要通知父进程)
  • 资源共享:多个进程之间共享同样的资源。为了做到这一点,需要内核提供互斥和同步机制。
  • 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程)此时控制进程徐望能够拦截另一个进程的所有陷入和异常,并能够及时知道他的状态改变。

进程间通信方式

image

1. 匿名管道(问题:管道特点)

管道也叫无名(匿名)管道
image
统计文件数目ls | wc -l

  • 管道其实是一个在内核内存中维护的缓冲器,这个缓冲器的存储能力是有限的,不同的操作系统大小不一
  • 管道拥有文件的特质:读写,匿名管道无文件实体,有名管道有文件实体,但不存储数据。可以按照操作文件的方式操作管道
  • 一个管道是一个字节流,使用管道时不存在消息或者消息边界的概念,从管道读取数据的进程可以读取任意大小的数据,而不管写入进程写入管道的数据块的大小是多少
  • 通过管道的数据是有顺序的,先写入的先读出,读出的顺序和他们被写入管道的顺序是一样的
  • 管道是单向的,半双工的
  • 从管道读数据是一次性操作,数据一旦被读走,他就从管道中被抛弃,释放空间以便写入更多的数据,在管道中无法使用lseek()来随机的访问数据
  • 管道只能在具有公共祖先的进程之间使用
    image

设置管道非阻塞

int flag = fcntl(pipefd[0], F_GETFL); // 获取原来的flag
flag |= O_NONBLOCK;                   // 修改flag的值
int ret = fcntl(pipefd[0], F_SETFL);  // 设置新的flag
2. 有名管道(FIFO)

匿名管道没有名字,只能用在亲缘关系的进程间通信,为了克服这个缺点,提出了有名管道(FIFO)

  • 有名管道提供了一个路径名与之关联,以FIFP文件形式存在文件系统中,只要访问该路径就能够彼此通过FIFO相互通信,因此通过FIFO不想管的进程也能交换数据。
    1.FIFO的内容在内存中
    2. 当使用FIFO的进城退出后,FIFO讲继续保存在文件系统中以便以后使用
    3. FIFO有名字
创建有名管道
 int ret = access("fifo1", F_OK);
    if(ret == -1) {
        printf("管道不存在,创建管道\n");
        
        ret = mkfifo("fifo1", 0664);

        if(ret == -1) {
            perror("mkfifo");
            exit(0);
        }       
    }
有名管道的注意事项:
1. 一个为只读而打开一个管道的进程会阻塞,直到另外一个进程为只写打开管道
2. 一个为只写而打开一个管道的进程会阻塞,直到另外一个进程为只读打开管道
  • 读管道:

    • 管道中有数据,read返回实际读到的字节数
    • 管道中无数据:
      • 管道写端被全部关闭,read返回0,(相当于读到文件末尾)
      • 写端没有全部被关闭,read阻塞等待
  • 写管道:

    • 管道读端被全部关闭,进行异常终止(收到一个SIGPIPE信号)
    • 管道读端没有全部关闭:
      • 管道已经满了,write会阻塞
      • 管道没有满,write将数据写入,并返回实际写入的字节数。
3. 信号
system V进程间通信方式
1. 消息队列
2. 共享内存
3. 信号量
Socket-不同主机(网络)进程间通信
posted @ 2021-03-28 20:10  tao10203  阅读(65)  评论(0)    收藏  举报