进程间通信

本文详细介绍了Linux系统中的进程间通信方法,包括管道(无名和有名)、信号、消息队列、共享内存段以及信号量数组,同时探讨了socket在网络编程中的应用。还涉及了如何使用信号处理函数进行进程间的同步操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

IPC: inter process communication

进程之间 的通信:实质---数据的交换

管道: pipe 无名管道 (亲缘关系的进程之间)

           fifo 有名管道 (可以在没有亲缘关系的 进程间)

信号: signal kill -9 pid

消息队列: 在linux内核中, A 进程发送一个 message 挂在队列上

                          B 进程去队列上把 message 读走

        ipcs 可以查看当前 linux系统内核中存在的消息队列

  共享内存段:

  信号量数组:

  socket 通信: 在不同的电脑的 进程之间 通信 (网络编程)

1. 管道

        在很久以前,进程之间的通信,可以用文件

        缺点: 慢,消耗大

        优点: 不需要再学习 IPC API函数

        有人利用系统的 API , 但文件的内容不在磁盘上(在内存中)在内存中搞一个文件

  1) 无名管道

         #include <unistd.h>

        int pipe(int pipefd[2]);

   参数: 是一个数组: pipefd[0] ---->读 描述符

                                     pipefd[1] ----->写 描述符

返回值: 0 成功 -1 失败

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

int main()
{
    int fd[2];
    char buf[100]={};
    pipe(fd); // fd[0]读描述符,fd[1]写描述符
    pid_t pid = fork();
    if(pid == 0)
    {
        close(fd[0]);
        write(fd[1],"hello",5);
    }
    else
    {
        close(fd[1]);
        read(fd[0], buf, sizeof(buf));
        printf("buf=%s\n",buf);
    }
}

  2) 有名管道

        mkfifo fifo1

  读写一个空的管道都会阻塞

        #include <sys/types.h>

        #include <sys/stat.h>

        int mkfifo(const char *pathname, mode_t mode);

  const char *pathname: fifo的路径名

  mode : 文件的权限

返回值: 0 成功,-1 失败

练习: 实现两个进程聊天: tom_from.c jerry_to.c

3 信号

         linux 中的信号有哪些 : kill -l

china@ubuntu:/mnt/hgfs/share/shuqi/ipc$ 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 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP

20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ

26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR

31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3

38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8

43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13

48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12

53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7

58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2

63) SIGRTMAX-1 64) SIGRTMAX

        SIGHUP: 控制终端挂起请求或者 控制终端 死亡的时候。

        SIGINT: CTRL+C 从键盘收到 SIGINT信号, 程序会终止

        SIGQUIT: CTRL+\ 从键盘收到 SIGquit信号,程序会终止

        SIGSEGV: 当 程序访问非法地址内存,收到 这个信号, 程序会终止

        SIGKILL: kill -9 杀死进程的信号

        SIGSTOP: 让进程暂停

        SIGCONT: 让进程继续

        SIGALRM: 闹钟信号, alarm()函数会参数这个信号,程序收到会终止

        SIGCHLD: 在父进程中,如果收到这个信号,代表子进程结束了

        SIGUSER1: 用户信号1 忽略

        SIGUSER2: 用户信号2 忽略

进程收到以上的信号的时候,通常会有3中处理方式:

(1). 捕捉信号: 把一个信号 与 用户自定义的 处理函数 关联起来 signal(如果收到该信号,就执行那个函数)

(2). 默认行为: 收到信号的时候,采用 操作系统的默认行为(终止)

(3). 忽略该信号

linux 信号相关的API函数

  发送信号: kill 函数 (可以发送给多个进程)

        #include <sys/types.h>

        #include <signal.h>

        int kill(pid_t pid, int sig);

pid: 接收者

        pid>0: 表示接收进程的PID

        pid=0: 发送给本组的进程

        pid=-1: 发送给所有进程(与权限发送的所有进程)

        pid<-1: 发送给进程组(进程组id)= -pid

        sig: 信号的id

返回值:0成功,-1失败

        #include 

        unsigned int alarm(unsigned int seconds);

        unsigned int seconds: 定时的秒数

        当 seconds 时间到了,就发送一个 SIGALRM 信号 给 自己

        alarm(0); ----> 如果闹钟时间还未到,取消闹钟

        int raise(int sig); 发送sig 信号给自己

        pause(); 等待一个信号,如果收到一个信号就返回

        大部分的信号的默认行为,进程如果收到 信号的默认行大部分都是终止。

改变信号的处理方式: 捕捉信号

        #include <signal.h>

        typedef void (*sighandler_t)(int);

        sighandler_t signal(int signum, sighandler_t handler);

int signum: 要捕捉的信号

handler: 处理方式 :有3种

        1. 自己写一个信号处理函数

        2. SIG_IGN 忽略该信号

        3. SIG_DFL 默认执行

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

void my_handle(int sig)
{
    printf("捕捉到了%d信号\n",sig);
}

int main()
{
    alarm(4);
    signal(SIGALRM,my_handle);
    signal(SIGQUIT,SIG_DFL);
//关联 SIGINT my_handle() 起来了
    pause();
}

练习:

司机售票员问题。

创建子进程代表售票员,父进程代表司机,同步过程如下:

售票员捕捉 SIGINT(代表开车 ctrl+c), 发SIGUSR1 给司机,司机打印 ("let's gogogo")

售票员捕捉 SIGQUIT(代表停车 ctrl+\), 发送SIGUSR2给司机,司 机打印("stop ths bus")

司机捕捉SIGTSTP(代表车到总站, ctrl + z), 发送 SIGUSR1给售票 员,售票员打印("please get off the bus")

子进程要捕捉: 售票员

signal: SIGINT, SIGQUIT, SIGUSR1

忽略哪些信号: SIGTSTP

父进程要捕捉:司机

signal: SIGTSTP,SIGUSR1, SIGUSR2

忽略哪些信号? SIGINT, SIGQUIT

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值