linux进程通信(一)

进程间通信的必要性

单进程没有并发能力,无法实现多进程协同。

进程通信的本质理解

1.进程通信的前提,让不同的进程看到同一块"内存"

2.看到的内存不属于任何进程,是共享的

进程间通信(IPC)发展

LINUX原生能提供 --- 管道
symstem V进程间通信 -- 多进程

共享内存、消息队列、信号量

POSIX进程间通信 -- 多线程

管道

只能单向通信,传输的都是资源,管道都是单向传输内容

管道实际是文件

管道的原理

管道通信

父进程task_struct{ //有指针指向文件描述符表},每个进程都有自己的一张文件描述符表files_struct,这张表的下标就是fd文件描述符,通过fd找到文件struct file{},

1.分别以读写的方式打开同一个文件

2.fork()创建子进程,子进程需要去复制父进程的files_struct{ }。因此父子进程能够看到同一份文件资源

3.匿名管道的调用实际上是调用了pipe这个函数,父进程创建管道文件是分别以读和写这两种方式打开文件,pipefd[0]表示读,pipefd[1]表示写。

模拟实现父子进程管道通信

        int pipe(int pipefd[2]); 成功:0;失败:-1

        函数调用成功返回r/w两个文件描述符。无需open,但需手动close。规定:pipefd[0] → r; pipefd[1] → w,就像0对应标准输入,1对应标准输出一样。向管道文件读写数据其实是在读写内核缓冲区。

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cstdlib> //stdlib.h
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define N 2
#define NUM 1024

using namespace std;

// child
void Writer(int wfd) // wfd pipefd[1]
{
    string s = "hello, I am child";
    pid_t self = getpid();
    int number = 0;

    char buffer[NUM];
    while (true)
    {
        sleep(1);

        char c = 'c';
        write(wfd, &c, 1); // strlen(buffer) + 1???
        number++;
        cout << number << endl;

        if(number >= 5) break;
    }
}

// father
void Reader(int rfd) 
{
    char buffer[NUM];

    while(true)
    {
        buffer[0] = 0; 
        // system call
        ssize_t n = read(rfd, buffer, sizeof(buffer)); //sizeof != strlen
        if(n > 0)
        {
            buffer[n] = 0; // 0 == '\0'
            cout << "father get a message[" << getpid() << "]# " << buffer << endl;
        }
        else if(n == 0) 
        {
            printf("father read file done!\n");
            break;
        }
        else break;
        // cout << "n: " << n << endl;
    }
}

//子进程写入父进程读取
int main()
{
    int pipefd[N] = {0};
    int n = pipe(pipefd);
    if (n < 0)
        return 1;
    pid_t id = fork();
    if (id < 0)
        return 2;
    if (id == 0)
    {
        // 子进程
        close(pipefd[0]);
        Writer(pipefd[1]);
        close(pipefd[1]);
        exit(0);
    }

    close(pipefd[1]);

    Reader(pipefd[0]);
    int p1 = 0;
    pid_t rid = waitpid(id, &p1, 0);
    if(rid < 0) return 3;

    close(pipefd[0]);


    sleep(5);
    return 0;
}

管道的特点

1.管道是用来进行具有血缘关系的进程间通信--常用于父子通信

2.管道具有通过让进程间协同,提供了访问控制

3.管道提供的是面向流式的通信服务--面向字节流

        父进程写入很多,但是子进程在sleep一段时间后再读取,会将父进程这一段时间的写入全部读取,写入10次可能一次读完

4.管道是基于文件的,文件的生命周期是随进程的,一个进程结束那么管道也就会结束

5.管道是单向通信,半双工通信的方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值