当前位置: 首页 > news >正文

信号和共享内存

信号

信号:实现进程间的通知机制
实现进程间的异步通信
软中断

     异步通信:接收方不知道什么时候发送方会发送数据。

2) SIGINT:ctrl + c 
让一个进程被打断
3) SIGQUIT:ctrl + \
让一个进程结束
9) SIGKILL:
强制让一个进程结束
11)SIGSEGV:
让一个进程结束(段错误)
13)SIGPIPE:
让一个进程结束(管道破裂)
14)SIGALRM:
让一个进程结束(定时时间到达)
17)SIGCHLD:
子进程结束时发送给父进程
18)SIGCONT:
让停止态的进程继续执行
19)SIGSTOP:
让运行态的进程进入停止态(暂停)强制停止
20)SIGTSTP:
ctrl + z   让进程进入暂停态,后台进程
来自终端的停止信号


10) SIGUSR1
12) SIGUSR2
用户可自定义的信号

      9) SIGKILL
19)    SIGSTOP
管理员信号:只能按照默认方式处理,不能够被忽略和捕获。

当进程收到一个信号,会打断该进程正在执行的任务,处理信号产生的事件;
当该事件处理完时,进程又从原来的位置继续执行。

signal:注册一个信号

       #include <signal.h>

       typedef void (*sighandler_t)(int);

       sighandler_t signal(int signum, sighandler_t handler);
功能:设置信号的处理方式(注册一个信号)
参数:
signum:要处理的信号的编号
handler:
SIG_IGN: 以忽略方式处理该信号(不处理)
SIG_DFL:以缺省方式处理(系统默认方式)
函数的地址:以捕获方式处理(自定义)

      返回值:
失败:NULL
自定义方式:返回自定义的函数入口。

     void (*sighandler_t)(int signum);
sighandler_t:执行信号任务处理函数的入口
参数:
signum:触发该任务函数的信号

注意:
1. 若信号不被注册,则按照默认方式处理
2. 信号只需注册一次即可;
3. 每次信号的到来都会触发一次信号任务处理函数;
4. 信号尽可能早注册。

#include <stdio.h>
#include <signal.h>
void handler(int signum)
{printf("%d signal comming\n", signum);
}
int main(int argc, const char *argv[])
{signal(SIGINT, SIG_IGN);
//	signal(SIGINT, SIG_DFL);//	signal(SIGKILL, handler);while (1){printf("hello world\n");sleep(1);}return 0;
}

3. 发送信号

     1)kill 命令
2)  kill();
int kill(pid_t pid, int sig);
功能:给指定的进程发送一个信号
参数:
pid:接收信号的进程PID
sig:信号的编号
返回值:
成功:0;
失败:-1;

#include <stdio.h>
#include "head.h"
#include "signal.h"void handler(int signum)
{int i = 3;while(i--){printf("Son is doing homework\n");sleep(1);}
//	kill(getppid(), SIGUSR2);exit(0);
}void handler2(int signum)
{printf("%d signal is comming\n", signum);wait(NULL);exit(0);
}int main(int argc, const char *argv[])
{pid_t pid = fork();if (pid > 0){signal(SIGCHLD, handler2);int i = 8;while (i--){printf("Father is working\n");sleep(1);}kill(pid, SIGUSR1);while (1){printf("xxxxxxxxxxxx\n");sleep(1);}}else if (0 == pid){signal(SIGUSR1, handler);while (1){printf("Son is playing games\n");sleep(1);}}else {perror("fork error");}return 0;
}

5)unsigned int alarm(unsigned int seconds);
功能:设置一个闹钟,当闹钟时间到达时,
向自己所在的进程发送一个SIGALRM的信号
参数:
seconds:设置的闹钟的定时时间
返回值:  
成功返回上次设定剩余的时间
上次未设定则返回0

#include "head.h"void handler(int signum)
{printf("%d signal comming\n", signum);alarm(5);
}
int main(int argc, const char *argv[])
{signal(SIGALRM, handler);unsigned int cnt = alarm(5);while (1){printf("hello world\n");sleep(1);}return 0;
}

共享内存

      共享内存:进程间效率做高的通信方式

1)通信原理

             使用内核空间中的内存区域共享数据。
使用内存映射技术,减少的数据的反复拷贝,提高了通信效率。

共享内存操作流程
IPC对象

       1)创建一个IPC key:
key_t ftok(const char *pathname, int proj_id);
2)  创建共享内存:
int shmget(key_t key, size_t size, int shmflg);
3)  建立共享内存段和用户空间的内存映射:
void *shmat(int shmid, const void *shmaddr, int shmflg);
4)  向共享内存写入数据--》通过用户空间的首地址
5)解除映射关系
int shmdt(const void *shmaddr);
6)删除共享内存
int shmctl(int shmid, int cmd, struct shmid_ds *buf);


#include <sys/types.h>
#include <sys/ipc.h>

       key_t ftok(const char *pathname, int proj_id);
功能:创建一个IPC key
参数:
pathname:路径
proj_id: 工程ID
注意:两个进程在创建KEY时必须使用相同的参数
返回值:
成功:IPC key
失败:-1
int shmget(key_t key, size_t size, int shmflg);
功能:创建一个共享内存
参数:
key:IPC key
size:共享内存的大小
会被扩展成PAGE_SIZE(4096bytes)的整数倍
shmflg:
IPC_CREAT | 0664
返回值:
成功:共享内存的ID
失败:-1

     void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:建立共享内存内存映射
参数:
shmid :共享内存id
shmaddr:映射的用户空间首地址
NULL:让操作系统分配
shmflg:
SHM_RDONLY:只读
!SHM_RDONLY:可读可写
返回值:
成功:映射的用户空间首地址
失败:(void *) -1

     int shmdt(const void *shmaddr);
功能:解除内存映射关系
参数:
shmaddr:要解除的用户空间首地址
返回值:
成功:0
失败:-1

int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:操作共享内存
参数:
shmid:要操作的共享内存id
cmd:要执行的操作指令
IPC_RMID:删除操作
buf:设置的参数
返回值:
成功:0
失败:-1

ipcs -a  查看内核中的IPC对象
ipcrm -s 删除信号量集
ipcrm -m 删除共享内存
ipcrm -m shmid 
ipcrm -M shmkey

6、信号量集

      实现进程间同步

7、消息队列

和管道类似,有同步效果
增加数据的等级(优先级:优先级数据越小,优先级越高)

#include "head.h"int main(int argc, const char *argv[])
{//ftok();//shmget();//shmat();//p-->//shmdt();//shmctl();key_t key = ftok(".", '!');if (key < 0){perror("ftok error");return -1;}printf("key = %x\n", key);int shmid = shmget(key, 4096,IPC_CREAT|0664);if (shmid < 0){perror("shmget error");return -1;}printf("shmid = %d\n", shmid);void *pmem = shmat(shmid, NULL, !SHM_RDONLY);if ((void *)-1 == pmem){perror("shmat error");return -1;}//*((int *)pmem) = 10;strcpy((char *)pmem, "hello");shmdt(pmem);//shmctl(shmid, IPC_RMID, NULL);return 0;
}

#include "head.h"int main(int argc, const char *argv[])
{//ftok();//shmget();//shmat();//p-->//shmdt();//shmctl();key_t key = ftok(".", '!');if (key < 0){perror("ftok error");return -1;}printf("key = %x\n", key);int shmid = shmget(key, 4096, IPC_CREAT|0664);if (shmid < 0){perror("shmget error");return -1;}printf("shmid = %d\n", shmid);void *pmem = shmat(shmid, NULL, !SHM_RDONLY);if ((void *)-1 == pmem){perror("shmat error");return -1;}printf("recv: %s\n", (char *)pmem);	shmdt(pmem);//shmctl(shmid, IPC_RMID, NULL);return 0;
}

http://www.lryc.cn/news/626172.html

相关文章:

  • 理解MCP:开发者的新利器
  • string 题目练习 过程分析 具体代码
  • Redis(10)如何连接到Redis服务器?
  • Git#revert
  • Pandas 入门到实践:核心数据结构与基础操作全解析(Day1 学习笔记)
  • 跟随广州AI导游深度探寻广州历史底蕴​
  • Linux Namespace 隔离的“暗面”——故障排查、认知误区与演进蓝图
  • Python day49.
  • 嵌入式第三十二天(信号,共享内存)
  • 机器学习概念(面试题库)
  • 8.19笔记
  • Python + 淘宝 API 开发:自动化采集商品数据的完整流程​
  • python新工具-uv包管理工具
  • RPC高频问题与底层原理剖析
  • Chrome插件开发【windows】
  • 【最新版】CRMEB Pro版v3.4系统源码全开源+PC端+uniapp前端+搭建教程
  • LLM(大语言模型)的工作原理 图文讲解
  • 网络间的通用语言TCP/IP-网络中的通用规则4
  • 大模型+RPA:如何用AI实现企业流程自动化的“降本增效”?
  • 基于SpringBoot+Vue的养老院管理系统的设计与实现 智能养老系统 养老架构管理 养老小程序
  • Linux系统部署python程序
  • SConscript 脚本入门教程
  • InfoNES模拟器HarmonyOS移植指南
  • Redis缓存加速测试数据交互:从前缀键清理到前沿性能革命
  • 图形化监控用数据动态刷新方法
  • Transformer入门到精通(附高清文档)
  • 内网后渗透攻击--隐藏通信隧道技术(压缩、上传,下载)
  • 常见的软件图片缩放,算法如何选择?
  • 【开源工具】基于社会工程学的智能密码字典生成器开发(附完整源码)
  • 字节开源了一款具备长期记忆能力的多模态智能体:M3-Agent