Linux系统进程间通信

zix 2026-9-29 71 9/29

        进程间通信(Inter Process Communication,IPC)指代进程间的信息交换,IPC有很多种实现方式,比如:管道通信、信号通信、消息队列、共享内存、信号重组、POSIX信号量等。进程间通信可以实现信息共享、资源共享以及进程控制等功能。

1.管道通信

        管道通信是Linux系统提供的一种通信方式,管道通信类似于水管,管道可以被分为读端和写端。在打开管道后,写端和读端都会被分配一个fd,同一个管道可以被同时读或者写,但是读端只可以读取,并且写端只可以写入。

        管道提供了一个内核缓冲区,在工作时,A进程调用write()函数写入到管道的内核缓冲区,写入完成后,A进程可以去执行其他工作,但是特别注意,如果缓冲区写满了,write函数会一直阻塞,必须等待B进程read之后才可以继续写入。如想避免阻塞,可以使用fcntl设置O_NONBLOCK将管道设置为非阻塞状态,或者使用poll/select监听管道。

        同样的,如果缓冲区为空的,在调用read函数读取时也会产生阻塞,只有当写端所有的fd关闭且缓冲区全空后,read函数才会读取到EOF不会被阻塞。在管道的所有读端的fd关闭之后,如果写端继续写入,程序会收到SIGPIPE信号则会直接导致进程意外终止。

        一个管道对象可以拥有多个fd,但是只能拥有一个读端和一个写端。同一个管道的同一个fd不能既读又写,但是一个管道可以被一边读一边写。管道通信最好是用哪端留哪端,不用立即关闭。

        同一个fd可以被多个进程同时持有并写入。从应用层的角度看这些写入是同时的,但在内核里,同一时刻只有一个写者能进入临界区,写入操作是被串行化的。通过这种串行写入,可以保证数据的完整性。特别注意,内核仅保证每次的写入是原子的,这个保证大小是有限制的,当数据大于PIPE_BUF的大小(4kb)后,数据将会被拆分为一段一段的写入,此时通常无法继续保证写入数据不出现交错。

        匿名管道:

        管道在Linux系统中以文件的形式存在,Linux系统中的管道文件分为匿名管道(pipe)和命名管道(fifo),匿名管道的特点是没有名称,故用户无法调用open进行打开,在Linux系统中提供了系统调用接口pipe用于创建匿名管道并且返回fd。

        pipe接口的标准pipe (int __pipedes[2]),传入为一个包含两个数据的整形数组,假设使用pipe(fd)调用后,fd[0]将为读端fd,fd[1]为写端fd。

        由于匿名管道的特性,其fd仅可以通过父进程创建后分发给子进程间进行通信,即其必须来源于同一个父进程。下面是一个匿名管道的使用例程。

#include <stdio.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
int main(){
    char str[20] = {};
    int fd[2];
    if(pipe(fd)){
        printf("创建管道失败!\n");
        return 0;
    };
    pid_t pid = fork();
    if(pid == -1){
        printf("子进程创建失败!\n");
        return 0;
    }
    if (pid == 0) {
        fflush(stdout);
        while (1) {
            read(fd[0], str, 20);
            printf("\n[子进程]:收到来自父进程的消息:%s\n", str);
            if (!strcmp(str, "结束通信")) {
                break;
            }
        }
        _exit(NULL);
    }else {
        while (1) {
            printf("[父进程]请输入要传递给子进程的消息:");
            fflush(stdout);
            scanf("%s", str);
            write(fd[1], str, strlen(str)+1);
            if (!strcmp(str, "结束通信")) {
                break;
            }
        }
        printf("结束!\n");
        wait(NULL);
    }
    return 0;
}

 

 

 

- THE END -

zix

9月29日23:45

0

非特殊说明,本博所有文章均为博主原创。

粤公网安备44011302005765号