6 Linux 进程间通信(IPC)


前言 (含目录)


/**
 * @author IYATT-yx
 * @brief 验证进程之间无法使用全局变量进行通信
 */
#include 
#include 
#include 

int num = 15;

int main(void)
{
   
    pid_t pid = fork();
    if (pid > 0)
    {
   
        printf("父: %d\n", num);
        ++num;
        printf("父: %d\n", num);
    }
    else if (pid == 0)
    {
   
        printf("子: %d\n", num);
        --num;
        printf("子: %d\n", num);
    }
    else
    {
   
        perror("fork");
    }
    
}

运行结果:
在这里插入图片描述

/**
 * @author IYATT-yx
 * @brief 进程间使用文件进行通信
 */
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main(void)
{
   
    int fdRW = open("/tmp/temp", O_CREAT | O_RDWR, 0664);
    if (fdRW == -1)
    {
   
        perror("open /tmp/temp");
        return -1;
    }

    // 子进程的虚拟地址空间和父进程基本一样 (除pid)
    // 可以使用同一个文件描述符,且都指向相同的文件
    pid_t pid = fork();
    if (pid == 0)
    {
   
        const char *str = "验证使用文件在进程间通信";
        write(fdRW, str, strlen(str));
        close(fdRW);
    }
    else if (pid > 0)
    {
   
        wait(NULL);

        char buf[1024];
        memset(buf, 0, 1024);
        lseek(fdRW, 0, SEEK_SET);
        read(fdRW, buf, sizeof(buf));
        printf("%s\n", buf);

        remove("/tmp/temp");
    }
}



IPC常用4种方式

  • 管道 (简单)
  • 内存映射 (通信的进程之间可以没有"血缘"关系)
  • 信号 (麻烦,但是信号属于操作系统的功能, 资源开销小)
  • 本地套接字 (稳定, 见后面网络编程部分)

pipe(匿名管道)
本质 ①内核缓冲区
②不占用磁盘空间,伪文件,但是可以当作文件读写
特点 ①两部分: 读端和写端各对应一个文件描述符,写端流入,读端流出
②操作管道的进程被
销毁后,自动销毁管道
③管道默认阻塞
原理 内部实现方式: 队列
* 环形队列
* 先进先出
缓冲区大小:
* 默认4K
* 大小根据实际情况适当调整
局限性 队列:
* 数据只能读取一次
半双工:
* 数据可以在一个信号载体的两个方向上传输,但是不能同时传输.
匿名管道:
* 有"血缘"关系的进程之间通信
/**
 * @author IYATT-yx
 * @brief 借助管道实现 ps ajx | grep bash , 父子进程通信 
 */
#include 
#include 
#include 

int main(void)
{
   
    // 创建管道
    // 下标0为读,下标1为写
    int fdPipe[2];
    if (pipe(fdPipe) == -1)
    {
   
        perror("pipe");
        return -1;
    }
    
    pid_t pid = fork();
    // 子进程执行 ps ajx
    // 执行结果默认是写到 STDOUT_FILENO
    // 此处需要重定向到 fdPipe[1], 写入管道
    if (pid == 0)
    {
   
        // 写时,关读
        close(fdPipe[0]);
        // 重定向文件描述符,写到终端改为写到管道
        dup2(fdPipe[1], STDOUT_FILENO);

        execlp("ps", "", "ajx", NULL);
        perror("execlp ps");
        return -1;
    }
    // 父进程执行 grep bash
    // 获取查找来源默认是从 STDIN_FILENO
    // 此处需要重定向到 fdPipe[0], 从管道读取
    else if (pid > 0)
    {
   
        // 读时,关写
        

你可能感兴趣的:(Linux,Linux系统编程)