温馨提示×

Linux进程通信:管道和信号详解

小樊
56
2025-12-23 19:29:32
栏目: 智能运维

在Linux系统中,进程间通信(IPC)是一种允许不同进程之间共享数据和信息的机制。管道和信号是两种常见的IPC方法。下面是对它们的详细解释:

管道(Pipes)

管道是一种半双工的通信方式,通常用于具有亲缘关系的进程之间(例如父子进程)。管道分为两种类型:

  1. 无名管道(Unnamed Pipes)

    • 无名管道是在进程创建时自动创建的,没有名字。
    • 它们通常用于父子进程之间的通信。
    • 管道有两个文件描述符,一个用于读取,一个用于写入。
    • 数据在管道中是单向流动的,从写入端流向读取端。

    创建和使用无名管道的示例

    #include <stdio.h>
    #include <unistd.h>
    
    int main() {
        int pipefd[2];
        pid_t pid;
        char buffer[10];
    
        // 创建管道
        if (pipe(pipefd) == -1) {
            perror("pipe");
            return 1;
        }
    
        // 创建子进程
        pid = fork();
        if (pid == -1) {
            perror("fork");
            return 1;
        }
    
        if (pid == 0) { // 子进程
            close(pipefd[1]); // 关闭写端
            read(pipefd[0], buffer, sizeof(buffer));
            printf("Child received: %s\n", buffer);
            close(pipefd[0]);
        } else { // 父进程
            close(pipefd[0]); // 关闭读端
            write(pipefd[1], "Hello from parent", 20);
            close(pipefd[1]);
        }
    
        return 0;
    }
    
  2. 命名管道(Named Pipes,FIFOs)

    • 命名管道是在文件系统中有一个名字的特殊文件。
    • 任何进程都可以通过这个名字打开管道进行通信,无论它们是否有亲缘关系。
    • 命名管道是全双工的,可以同时进行读写操作。

    创建和使用命名管道的示例

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    int main() {
        int fd;
        char buffer[10];
    
        // 创建命名管道
        if (mkfifo("myfifo", 0666) == -1) {
            perror("mkfifo");
            return 1;
        }
    
        // 打开命名管道进行读写
        fd = open("myfifo", O_RDWR);
        if (fd == -1) {
            perror("open");
            return 1;
        }
    
        // 写入数据
        write(fd, "Hello from FIFO", 20);
    
        // 读取数据
        read(fd, buffer, sizeof(buffer));
        printf("Read from FIFO: %s\n", buffer);
    
        // 关闭文件描述符
        close(fd);
    
        // 删除命名管道
    unlink("myfifo");
    
    return 0;
    

信号(Signals)

信号是一种异步的通知机制,用于通知进程某个事件已经发生。信号可以由操作系统、其他进程或进程自身发送。常见的信号包括:

  • SIGINT:中断信号,通常由Ctrl+C触发。
  • SIGTERM:终止信号,用于请求进程终止。
  • SIGKILL:强制终止信号,无法被捕获或忽略。
  • SIGUSR1SIGUSR2:用户自定义信号。

发送和处理信号的示例

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

// 信号处理函数
void signal_handler(int signum) {
    printf("Received signal %d\n", signum);
}

int main() {
    // 注册信号处理函数
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);

    printf("Process is running. Press Ctrl+C to send SIGINT or kill -TERM <pid> to send SIGTERM.\n");

    // 主进程循环
    while (1) {
        sleep(1);
    }

    return 0;
}

在这个示例中,当进程接收到SIGINTSIGTERM信号时,会调用signal_handler函数进行处理。

总结

  • 管道:用于具有亲缘关系的进程之间的单向或双向通信。
  • 信号:用于异步通知进程某个事件已经发生,可以由操作系统、其他进程或进程自身发送。

这两种IPC机制在Linux系统中非常常用,掌握它们对于编写高效、可靠的系统程序非常重要。

0