共享内存 进程间通信

本文深入探讨了信号处理机制,包括SIGKILL、SIGALRM等信号的发送与接收原理,并详细介绍了进程间通信(IPC)机制,如共享内存、信号灯及消息队列的使用方法。

kill SIGKILL
raise 向自己的进程发送函数
SIGALRM 不是立马发送 是定时等待发出 定时一段时间才发信号 只能发送给当前进程 和raise 一样
uint alarm(uint second)没有告诉内核发送什么信号 让内核延迟second 的时间再发送
发送给当前进程 在信号接受前进程不能结束 收到信号终止进程

信号的接收
sleep
pause 当前进程处于睡眠状态
ctrl +Z SIGTSTP
ctrl +c 键盘驱动来发送 SIGINT 信号在用用户输入 字符Ctrl+c时候发出 终止终端驱动程序发送此信号 并送到前台进程中的每一个进程

信号的处理
signal 自己处理信号的方法告诉 这样收到信号的进程就会按你的方式处理
void (*signal(int signum,void (*handler(int )))(int));
void (*handler)(int) 函数指着变量
返回值 函数指针
signal 处理 那个信号 告诉内核怎么处理这个信号
SIG_IGN 忽略该信号
SIG_DFL 采用系统默认方式处理信号
自定义的信号处理函数指针

告诉内核 处理哪一个信号 第二个 按什么方式处理
signal(14,SIG_IGN) 忽略信号

IPC
共享内存
信号灯
消息队列

进程A 和进程B 通信 通过内核的IPC 内核空间是不存在的 必须在内核空间里创建 最后删除 和文件IO处理思想是一样的 函数形式不一样 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201221140828405.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BlamF5MjM=,size_16,color_FFFFFF,t_70
在这里插入图片描述


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

int main()
{int shmid;
shmid=shmget(IPC_PRIVATE,128,0777);//每次用IPC_PRIVATE 操作时共享内存的key都是一样的都是0 有缘
//ftok 获得  无缘 
IF(shmid<0)
{
printf("create shar memory failure\n");
return -1;
}
printf("create share memory success shmid%d\n",shmid);
system("ipcs -m");
}

在这里插入图片描述
将内存映射到用户空间的地址中去
不必每次进入到内核读写
shmat(int shmid ,const void *shmaddr ,int shmflg);
在这里插入图片描述
通过fgets ()
共享内存创建之后 一直存在内核中 直到被删除或者被系统关闭
共享内存和管道不一样 读取之后 内存仍然窜在其共享内存中
使用完需要释放共享内存
shmdel

在这里插入图片描述

shmget 创建缓存
shmat
shmdt
shmctl
ftok 用来创建key 给shmget第一个参数用
无缘进程之间的共享内存 通信

服务器

#include "sys/types.h"
#include <signal.h>
#include <unistd.h>

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/shm.h>
struct mybuf{
    int pid;
    char buf[128];
};
void myfun()
{
    
    return ;
}
int main()
{
  int shmid;
  int key;
  struct mybuf *p;
  int pid;
  key=ftok("./a.c",'a');
  if(key<0)
  {
      printf("ftok failure\n");
      return -2;
  }

  printf("create key success\n");
  shmid=shmget(key,128,IPC_CREAT |0777);
  if(shmid<0)
  {
      printf("create share momery failure\n");
  return -1;
  }
    printf("create share momery success shmid =%d\n",shmid);


  signal(SIGUSR2,myfun);
  p=(struct mybuf *)shmat(shmid,NULL,0);
  if(p==NULL)
  {
      printf("parent process shmat failure\n");
      return -3;
  }
  p->pid=getpid();
  pause();// client read server pid
  pid=p->pid;

  while(1)
  {
      printf("parent process start write share memory:\n");
      fgets(p->buf,128,stdin);
      kill(pid ,SIGUSR1);
      pause();//wait client proces read
  }
    return 0;
}

客户端

#include "sys/types.h"
#include <signal.h>
#include <unistd.h>

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/shm.h>
struct mybuf{
    int pid;
    char buf[128];
};
void myfun()
{
   
    return ;
}
int main()
{
  int shmid;
  int key;
  struct mybuf *p;
  int pid;
  key=ftok("./a.c",'a');
  if(key<0)
  {
      printf("ftok failure\n");
      return -2;
  }

  printf("create key success\n");
  shmid=shmget(key,128, IPC_CREAT| 0777);
  if(shmid<0)
  {
      printf("create share momery failure\n");
  return -1;
  }
    printf("create share momery success shmid =%d\n",shmid);


  signal(SIGUSR1,myfun);
  p=(struct mybuf *)shmat(shmid,NULL,0);
  if(p==NULL)
  {
      printf("parent process shmat failure\n");
      return -3;
  }
  //read share memory 
	pid=p->pid;
	p->pid=getpid();


	kill(pid,SIGUSR2);//kill signal



  while(1)
  {
      pause();//Wait server write data to share memory 
      printf("client process receve data from memory :%s\n",p->buf);
      
      kill(pid,SIGUSR2); // SERVER CAN WRITE SHARE MEMORY 
  }
    return 0;
}
### 原理 当两个进程通过页表将虚拟地址映射到物理地址时,在物理地址中有一块共同的内存区,即共享内存,这块内存可以被两个进程同时看到。这样当一个进程进行写操作,另一个进程进行读操作就可以实现进程间通信。不过,要确保一个进程在写的时候不能被读,因此使用信号量来实现同步与互斥[^3]。 ### 方法 基于共享内存的通信方式,进程A可以直接将从键盘获取的数据写到共享内存中,进程B直接从共享内存中读取数据并打印到显示器上。在Linux中,基于System V共享内存方式实现进程间通信会涉及一些相关函数调用接口,例如创建共享内存的`shmget`函数,其原型如下: ```c #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int shmflg); ``` ### 示例 以下是一个获取共享内存属性并输出共享内存大小的示例代码: ```c #include <stdio.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/shm.h> #define KEY 0x89898989 int main() { int shmid = shmget(KEY, 1024, IPC_CREAT | 0664); if (shmid < 0) { perror("shmget"); return -1; } struct shmid_ds buf; shmctl(shmid, IPC_STAT, &buf); // 获取 共享内存段 大小 printf("shm size : %ld字节\n", buf.shm_segsz); return 0; } ``` 运行该程序后,会输出共享内存的大小,例如`shm size : 1024字节`。当使用`ipcrm`命令或者`shmctl`函数删除共享内存之后,共享内存段就被释放了,共享内存标识符被设置为`0x00000000`,表示任何进程都无法通过之前的标识符来寻找该共享内存共享内存的状态会被设置成`dest(destroy)`,表示被销毁。如果这块被释放的共享内存块依然还有进程映射,即`nattch`不为0,则描述共享内存的结构体就不会被释放,直到所有依附于该共享内存的进程全部分离后,即`nattch`为0时,描述该共享内存的结构体才会被释放[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值