进程间通信

- 管道
匿名管道:用于父进程和子进程间的通信
有名管道:用于运行于同一系统中的任意两个进程间的通信

-消息队列
函数原型:

// 创建和获取 ipc 内核对象 --IPC_CREAT
int msgget(key_t key, int msgflag);
// 将消息发送到消息队列 --IPC_NOWAIT
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
// 从消息队列获取消息 --IPC_NOWAIT/0
int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
// 查看、设置、删除 ipc 内核对象(用法和 shmctl 一样) 删除--IPC_RMID
int msgctl(int msqid, int cmd, struct msqid_ds *buf);

- 共享内存
将两个进程不同的虚拟地址空间映射到一块相同的物理地址空间
函数原型:

//创建共享内存
int shmget(key_t key, size_t size, int shmflg);
//挂接共享内存
void *shmat(int shmid, const void *shmaddr, int shmflg);
//解除挂接共享内存
int shmdt(const void *shmaddr);
//销毁共享内存 删除--IPC_RMID
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

在这里插入图片描述

- 信号

使用举例:

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

//信号处理函数
void signalHandler(int signum)
{
   printf("Interrupt signal %d received\n",signum);
   exit(signum);
}

int main(int argc,char argv[])
{
   //信号处理函数绑定
   signal(SIGINT,signalHandler);
   int i = 1;
   while (1)
   {
       printf("going to sleep %d...\n",i++);
       if( i > 10 )
       {
          //主动发送信号
           raise(SIGINT);
           printf("send SIGINT\n");
       }
       sleep(1);
   }
   return 0;
}

信号发送与处理过程:
1.假设我们有一个进程 A,main 函数里面调用系统调用进入内核。
2.按照系统调用的原理,会将用户态栈的信息保存在 pt_regs 里面,记住原来用户态是运行到了 line A 的地方。
3.在内核中执行系统调用读取数据。
4.当发现没有什么数据可读取的时候,将进程状态设置为 TASK_INTERRUPTIBLE可中断的睡眠状态,让出 CPU,如果有信号来的话,是可以唤醒它的。
5.当给进程 A 发送一个信号,其实就是找到进程 A 的 task_struct,若信号值小于32为不可靠信号则加入信号集合(存在同个信号则忽略),若信号值大于32为可靠信号则加入信号链表。
6.当发现有信号到来的时候进程A被唤醒,返回用户态执行信号处理函数。
7.信号处理函数就执行完后,接着原本系统调用之后运行,当然这个系统调用返回的是它被中断导致没有执行完的错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值