当前位置:网站首页>进程间通讯 (IPC 技术) - 信号
进程间通讯 (IPC 技术) - 信号
2022-08-03 05:23:00 【纸鸢805】
IPC(Inter-Process Communication)进程间通信,提供了各种进程间通信的方法。在Linux C编程中有几种方法
(1) 半双工Unix管道
(2) FIFOs(命名管道)
(3) 消息队列
(4) 信号量
(5) 共享内存
(6) 网络Socket
1. 信号 (该文章信号是Ubuntu Linux 虚拟机环境下)
在 Ubuntu 中
kill -n 发送第 N 个信号 比如第九个 是 杀死
1~ 31 不可靠信号 34~64 可靠信号
其中 SIGUSR1 与 SIGUSR2 可以用户自定义;
void (* functon)(int) 函数指针 名称在后面的就是该数据的属性
1.1signal库函数
如果想让程序能够处理信号,可以使用 signal库函数,要引入头文件<signal.h>
void (*signal(int sig, void (*func)(int))) (int);void (*func)(int) 是函数指针
其中int 形参 可以用来判断信号ID;
配合kill 使用 , signal绑定信号与函数指针, 使用kill 发送给进程;
kill( 进程ID , 信号 ); //发送信号给目标进程特点:
1. 优先级最高,可以打破死循环先执行信号中函数指针的内容,再回去继续进行死循环。
2. 接收的信号没有绑定函数, 会导致进程直接结束代码, 但是进程不会结束,子进程的话会进入僵尸状态。
3. 不可靠信号,如果连续发送太快进程在执行会不管新接收的信号, 一次只处理一条信号。可靠信号就没这个问题。
4. 进程接受到的信号无法识别执行什么,就会意外结束程序, 如果在子进程当中可能会引起僵尸状态。
2.1 无参信号:头文件如果不知道 在Ubuntu 终端中使用 man 函数名 来查询)
signal 与 kill 配合
//信号方案1 不带参
signal(SIGUSR1, signal_funtion);
pid_t id = 0;
id = fork();
int state = 0;
if ( id > 0 )
{
sleep(5);
for (int i = 0; i < 3 ; i++)
{
sleep(2);
//给子进程 id 发送信号
kill(id, SIGUSR1);
}
//接收子进程状态
wait(&state);
while (true)
{
}
}
else
{
while (1)
{
sleep(1);
cout << "子进程: " << getpid() << endl;
}
exit(1);
}2.2 带参信号:(Ubuntu 目前只能发送int数据)
sigaction 与 sigqueue (该组合也可进行无参信号发送,就是没有signal 方便)
union sigval 该结构体就是传递的带参, 其中只有int能用, 另一个保留的void *参数 暂时官方没完善用不了。
//信号方案2 带参信号
pid_t id = 0;
int state = 0;
struct sigaction act;
act.sa_sigaction = sigaction_function;
act.sa_flags = SA_SIGINFO; //表示设置为带参信号
/*
//这是不带参的写法
struct sigaction act2;
act2.sa_handler = test2;
act2.sa_flags = 0;
*/
sigaction(SIGUSR1, &act, NULL); //绑定信号
//子进程在信号之后生成
id = fork();
if ( id > 0 )
{
sleep(5);
for (int i = 0; i < 3 ; i++)
{
sleep(2);
union sigval value;
value.sival_int = 123;
//给子进程 id 发送信号
sigqueue(id, SIGUSR1, value);
}
//接收子进程状态
wait(&state);
while (true)
{
}
}
else
{
while (1)
{
sleep(1);
cout << "子进程: " << getpid() << endl;
}
exit(1);
}2.3 信号冲突: ※
两个及以上的命令互相影响,造成程序异常。
信号冲突有两种情况:
不过只解决异种信号冲突的情况, 同种信号(同一个重复发送)会自动排队运行。
//这两个函数绑定 10 与 12 信号 用来测试信号冲突
void test1( int num )
{
cout << " test1 run : " << getpid() << endl;
sleep(20);
cout << " test1 over " << endl;
}
void test2(int num)
{
cout << " test2 over " << endl;
}
//信号冲突 (两个信号及以上, 执行一个信号的时候另外的信号也传递过来互相影响)
/*
两种情况
情况1 :
※情况1:一个信号正在执行处理函数,还在执行没做完,接收到异种信号,
执行函数被打断立刻执行异种信号处理,异种处理完再回去处理未处理完的第一个信号的逻辑
情况2:一个信号正在执行处理函数,还在执行没做完,接到铜钟信号,
执行函数继续执行,完成之后再次下一次函数
口诀: 异种打断, 同种排队
*/
struct sigaction act1;
act1.sa_handler = test1;
act1.sa_flags = 0;
struct sigaction act2;
act2.sa_handler = test2;
act2.sa_flags = 0;
//清空信号集
sigemptyset( &(act1.sa_mask) );
//添加信号集 把SIGUSR2 加到
//sa_mask
/*sigset_t sa_mask 是一个信号集,在调用该信号捕捉函数之前,
将需要block的信号加入这个sa_mask,仅当信号捕捉函数正在执行时
,才阻塞sa_mask中的信号,当从信号捕捉函数返回时进程的信号屏蔽字复位为原先值。*/
sigaddset(&(act1.sa_mask) , SIGUSR2);
sigaction(SIGUSR1 , &act1, NULL);
sigaction(SIGUSR2, &act2, NULL);
while (1)
{
cout << " 进程正在运行: pid = " << getpid() << endl;
sleep(1);
}2.4 信号未绑定函数指针 (未决信号)
//信号没绑定方法解决方法 使用信号集过滤掉
sigset_t s; // 定义一个信号集
sigemptyset(&s); //清空信号集
sigaddset(&s, SIGUSR1); //添加信号集
sigaddset(&s, SIGUSR2); //添加信号集
//启用信号集过滤
if ( sigprocmask(SIG_BLOCK, &s, NULL) < 0 )
{
perror(" sigprocmask error! ");
}
while (1)
{
cout << " 进程正在运行 ... pid = " << getpid() << endl;
sleep(1);
}边栏推荐
猜你喜欢
随机推荐
中国融资租赁行业市场投资分析与前景战略规划建议报告2022~2028年
Oracle 密码策略详解
Execute the mysql script file in the docker mysql container and solve the garbled characters
Ansible installation and deployment detailed process, basic operation of configuration inventory
ASP.NET MVC:自定义 Route
Flask,7
嵌入式实验四
【DC-5 Range Penetration】
[CSRF, SSRF, XXE, PHP deserialization, Burpsuite]
Sqli-labs-master shooting range 1-23 customs clearance detailed tutorial (basic)
Django从入门到放弃三 -- cookie,session,cbv加装饰器,ajax,django中间件,redis缓存等
取某一区间中素数的个数--洛谷P1865 A % B Problem
中国水环境治理行业投融资分析及“十四五”规划建议报告2022~2028年
布尔盲注需简化代码
动漫 吞噬星空
【 Nmap and Metasploit common commands 】
Sentinel初次使用Demo测试
中国食品产业园区行业前景规划建议及投融资模式分析报告2022~2028年
mysql 客户端SSL错误2026 (HY000)
中国食品微生物检测行业深度监测及投资战略规划建议报告2022~2028年









