无名管道、有名管道、信号、信号处理

1. 进程间通信(IPC)

进程间通信(IPC)是指在不同进程之间交换数据或信息的机制。常见的 IPC 方法包括:

1.1 管道(Pipe)
  • 无名管道(Anonymous Pipe):

    • 只能用于具有亲缘关系的进程间通信(如父子进程)。

    • 使用 pipe() 系统调用创建。

    • 特点:

      • 读操作:如果管道中有数据,则直接读取;如果没有数据,会阻塞等待。

      • 写操作:如果管道中有读端且未满,则直接写入;如果管道已满,会阻塞等待。

      • 如果管道中没有读端,写入数据会导致管道破裂(SIGPIPE 信号)。

  • 有名管道(Named Pipe/FIFO):

    • 可以用于任意两个进程之间的通信。

    • 使用 mkfifo() 系统调用创建。

    • 特点:

      • 必须读写两端同时打开,才能继续执行;否则会阻塞等待。
1.2 信号(Signal)
  • 定义:

    • 提供一种内核层与用户层之间的通知机制。

    • 信号是一种软件中断,用于通知进程某些事件的发生。

  • 信号类型:

    • SIGINT(2):中断信号(如 Ctrl+C)。

    • SIGQUIT(3):退出信号(如 Ctrl+\)。

    • SIGSEGV(11):段错误。

    • SIGPIPE(13):管道破裂。

    • SIGALRM(14):定时信号。

    • SIGCHLD(17):子进程结束。

    • SIGSTOP(19):停止进程。

    • SIGTSTP(20):挂起进程(如 Ctrl+Z)。

    • SIGIO(29):异步 I/O 信号。

  • 对信号的处理方式:

    1. 忽略:信号来了,不处理该信号。

    2. 缺省:信号来了,按照默认的方式处理信号。

    3. 捕捉:信号来了,按照指定的方式处理信号。

    • 注意:SIGKILL(9)和 SIGSTOP(19)不能被忽略或捕捉。
  • 函数接口:

    复制代码
    typedef void (*sighandler_t)(int);
    sighandler_t signal(int signum, sighandler_t handler);
    • 功能:修改信号的处理方式。

    • 参数:

      • signum:信号编号。

      • handler:信号处理方式(SIG_IGN 忽略,SIG_DFL 缺省)。

    • 返回值:

      • 成功返回之前的信号处理函数。

      • 失败返回 SIG_ERR。

1.3 消息队列(Message Queue)
  • 提供一种在进程间传递消息的机制。

  • 消息队列允许一个或多个进程向队列中写入消息,同时允许一个或多个进程读取这些消息。

1.4 共享内存(Shared Memory)
  • 允许多个进程共享同一块内存区域。

  • 提供高效的进程间通信,但需要同步机制(如互斥锁)来避免数据竞争。

1.5 信号量(Semaphore)
  • 提供一种同步机制,用于控制对共享资源的访问。

  • 函数接口:

    复制代码
    int sem_init(sem_t *sem, int pshared, unsigned int value);
    int sem_destroy(sem_t *sem);
    int sem_wait(sem_t *sem);
    int sem_post(sem_t *sem);
    • sem_init:初始化信号量。

    • sem_destroy:销毁信号量。

    • sem_wait:申请信号量资源(资源数 - 1)。

    • sem_post:释放信号量资源(资源数 + 1)。

1.6 套接字(Socket)
  • 提供一种在不同主机上的进程之间进行通信的机制。

  • 支持多种协议(如 TCP/IP、UDP/IP)。


2. 管道的详细说明

2.1 无名管道
  • 创建:

    复制代码
    int pipe(int pipefd[2]);
    • 功能:创建操作管道的两个文件描述符。

    • 参数:

      • pipefd[0]:读文件描述符。

      • pipefd[1]:写文件描述符。

    • 返回值:

      • 成功返回 0。

      • 失败返回 -1。

2.2 有名管道
  • 创建:

    复制代码
    int mkfifo(const char *pathname, mode_t mode);
    • 功能:创建管道文件。

    • 参数:

      • pathname:管道文件名。

      • mode:权限。

    • 返回值:

      • 成功返回 0。

      • 失败返回 -1。


3. 信号的详细说明

3.1 信号处理
  • 信号列表:

    • 使用 kill -l 命令查看所有信号。

    • 示例:

      复制代码
      1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
      6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
      11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
  • 信号处理方式:

    • 忽略 :SIG_IGN。

    • 缺省 :SIG_DFL。

    • 捕捉:自定义处理函数。

  • 示例代码:

    复制代码
    #include <stdio.h>
    #include <signal.h>
    
    void handle_sigint(int sig) {
        printf("SIGINT signal received\n");
    }
    
    void handle_sigquit(int sig) {
        printf("SIGQUIT signal received\n");
    }
    
    int main() {
        signal(SIGINT, handle_sigint);  // 捕捉 SIGINT
        signal(SIGQUIT, handle_sigquit);  // 捕捉 SIGQUIT
    
        printf("Press Ctrl+C or Ctrl+\\ to test signals\n");
        while (1) {
            // 等待信号
        }
    
        return 0;
    }
3.2 定时信号
  • alarm():

    复制代码
    unsigned int alarm(unsigned int seconds);
    • 功能:定时 seconds 秒后给当前进程发送 SIGALRM 信号。

    • 参数:

      • seconds:秒数。
    • 返回值:

      • 成功返回之前定时剩余的秒数。

      • 如果之前没有定时返回 0。

3.3 发送信号
  • kill():

    复制代码
    int kill(pid_t pid, int sig);
    • 功能:向 pid 对应的进程发送 sig 信号。

    • 参数:

      • pid:目标进程的 PID。

      • sig:信号编号。

    • 返回值:

      • 成功返回 0。

      • 失败返回 -1。


4. 总结

  • 管道:

    • 无名管道:用于具有亲缘关系的进程间通信。

    • 有名管道:用于任意两个进程之间的通信。

  • 信号:

    • 提供内核层与用户层之间的通知机制。

    • 可以通过 signal() 设置信号处理方式。

  • 消息队列:

    • 提供进程间传递消息的机制。
  • 共享内存:

    • 提供高效的进程间通信,但需要同步机制。
  • 信号量:

    • 提供同步机制,用于控制对共享资源的访问。
  • 套接字:

    • 提供不同主机上的进程之间进行通信的机制
相关推荐
2401_868534783 分钟前
软考网络规划设计师SSL协议知识点详解
服务器·网络
thefool11226615 分钟前
TCP 1
java·1024程序员节
Escalating_xu20 分钟前
【Linux 网络编程】手写序列化与反序列化:从 x op y 到能校验的文本协议
linux·运维·网络
LCG米35 分钟前
STM32 DMA 多通道链式传输实测:请求仲裁顺序错位根因、半满中断乒乓与高速并发搬运落地
stm32·单片机·嵌入式·1024程序员节
todoitbo2 小时前
在 Ubuntu ARM64 上运行 Q1 V3.0 MuJoCo 模型:加载、步进和单执行器响应
linux·运维·ubuntu·ai·机器人·仿真教程·启元
企业数字化笔记2 小时前
视频人体姿态怎么做三维可视化?2D关键点、深度局限与技术选型
人工智能·算法·音视频
AR-26710-2 小时前
Linux Day26——传输层与三次握手
linux·运维
金銀銅鐵3 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
?abc!3 小时前
(数组)581. 最短无序连续子数组
数据结构·算法·leetcode
POMAGTOR3 小时前
【磁吸式连接器选型工程解析:结构原理、应用场景与选型可靠性要点】
网络·嵌入式硬件