常见问题
解决 vscode 远程连接虚拟机上 ubuntu 系统,在编写代码时用到的 Linux 系统函数或者某些
常量不提醒或者报红色波浪线的问题:
信号的屏蔽和解除
信号的屏蔽和解除屏蔽函数的基本使用:
#include <stdio.h>
#include "header.h"
void handler(int signum)
{
printf("%d--%d\n", getpid(), signum);
}
// 信号的发送和信号的处理是异步的(各自执行各自的)
// 当信号到达后,就会执行信号处理函数,此时sleep打断,当执行函数执行完毕后,sleep不会继续执行
int main(int argc, char const *argv[])
{
printf("当前进程id是 %d\n", getpid());
// 循环给所有信号绑定处理函数
for (int i = 1; i <= 64; i++)
{
if (i == SIGKILL || i == SIGSTOP || i == 32 || i == 33) // 9, 19, 32, 33
{
continue;
}
// 给其他信号绑定处理函数
signal(i, handler);
}
// 定义信号集的结构体变量
sigset_t set;
// 清理集合中的信号
sigemptyset(&set);
// 填充所有信号
// sigfillset(&set);
for (int i = 1; i <= 64; i++)
{
if (i == 32 || i == 33)
{
sigaddset(&set, i);
}
}
// 删除某个信号
sigdelset(&set, 12);
// 调用函数屏蔽所有信号
int r = sigprocmask(SIG_BLOCK, &set, NULL);
if (r == -1)
{
perror("sigprocmask failed");
return -1;
}
puts("所有信号已经屏蔽!");
// 过一段时间,//延时20秒
sleep(20);
// 解除所有被屏蔽的信号
int r2 = sigprocmask(SIG_UNBLOCK, &set, NULL);
if (r2 == -1)
{
perror("unmask sigprocmask failed");
return -1;
}
// 延时20秒
sleep(20);
puts("所有信号已经解除屏蔽!");
puts("程序即将退出!");
return 0;
}
可靠信号和不可靠信号
#include <stdio.h>
#include "header.h"
void handler(int signum)
{
printf("%d--%d\n", getpid(), signum);
}
//信号的发送和信号的处理是异步的(各自执行各自的)
//当信号到达后,就会执行信号处理函数,此时sleep打断,当执行函数执行完毕后,sleep不会继续执行
int main(int argc, char const *argv[])
{
printf("pid=%d\n", getpid());
//循环给所有信号绑定处理函数,除去9
for(int i = 1; i<=64; i++)
{
if(i == SIGKILL || i == 32 || i==33)
{
continue;
}
//绑定处理函数
signal(i, handler);
}
sigset_t set;
//清空操作
sigemptyset(&set);
//填充所有信号
sigfillset(&set);
//调用函数屏蔽信号
if (-1 == sigprocmask(SIG_BLOCK, &set, NULL))
{
perror("sig mask failed");
return -1;
}
puts("所有信号已经被屏蔽\n");
//循环给当前进程发送多次可靠信号---
for(int i = 0; i<5; i++)
{
//当屏蔽解除后,所有可靠信号都接受到并执行了处理函数
//raise(46);
//当屏蔽解除后,所有不可靠信号只接收到一个,因为其他信号嵌套丢失了
raise(6);
}
puts("10秒之后解除屏蔽");
sleep(10);
//调用函数解除屏蔽
if (-1 == sigprocmask(SIG_UNBLOCK, &set, NULL))
{
perror("sig unmask failed");
return -1;
}
puts("进程结束");
return 0;
}
发送信号并携带数据
发送带数据的信号代码:
#include <stdio.h>
#include "header.h"
int main(int argc, char const *argv[])
{
//通过命令行传输数据
if (argc < 2)
{
puts("缺少参数!");
return -1;
}
printf("argv[1]: %s\n", argv[1]);
//定义变量存储信号编号
int signum;
int a =0;
while (1)
{
printf("请输入要发送的信号:\n");
scanf("%d", &signum);
//排除非信号编号的值
if (signum<1 || signum >64 || signum == 32 || signum == 33)
{
printf("不能发送这样的信号!\n");
break;
}
//定义共用体作为写到的数据块
union sigval value;
//设置携带的数据
//value.sival_int = 666666;
a = 200;
value.sival_ptr = &a;
printf("send: %p\n", &a);
//调用sigqueue函数发送信号
int r = sigqueue(atoi(argv[1]), signum, value);
if (r == -1)
{
perror("sigqueue failed");
return -1;
}
}
return 0;
}
接收带数据的信号代码
#include <stdio.h>
#include "header.h"
//类型重命名
typedef struct sigaction SigAction_t;
//定义信号处理函数
// void handler(int signum)
// {
// printf("rcv: %d\n", signum);
// }
void data_handler(int signum, siginfo_t* info, void* a)
{
if (signum == SIGINT)
{
printf("si_value: %p\n", info->si_value.sival_ptr);
printf("rcv: %d, %d, %d, %d\n", info->si_pid, info->si_int, info->si_signo, *(int*)(info->si_value.sival_ptr));
}
}
int main(int argc, char const *argv[])
{
//定义sigaction函数需要的结构体变量
SigAction_t act1;
//act1.sa_handler = handler;
//指定能够接收数据的处理函数
act1.sa_sigaction = data_handler;
act1.sa_flags = SA_SIGINFO;
//清空默认的信号集
sigemptyset(&act1.sa_mask);
//调用函数接收发送过来的消息, ctrl+c
int r = sigaction(SIGINT, &act1, NULL);
if (r == -1)
{
perror("sigaction failed");
return -1;
}
//死循环--保活程序等待信号的到来,不断的打印当前进程id
while (1)
{
printf("main running ..... %d\n", getpid());
sleep(1);
}
return 0;
}
问题的原因: 虽然可以携带指针类型的数据,但发送程序和接收程序是两个进程,两个进程
是独立的虚拟内存空间,所以不能用一个进程的内存地址获取另外一个进程同样内存地址上的
数据;故运行会报段错误(野指针访问数据)
解决办法:在父子进程间可以发送携带指针的数据,因为子进程拷贝了父进程的虚拟内存空间
和数据,所以可以通过同样的内存地址找到同样的数据
定时器 alarm
alarm 是一次性定时器,如果要实现循环定时器,需要在处理函数中再次调用 alarm 函数
alarm 的使用:
#include <stdio.h>
#include "header.h"
void handler(int signum)
{
printf("rcv: %d\n", signum);
alarm(5);
}
int main(int argc, char const *argv[])
{
//调用alarm函数设置定时器
alarm(3);
//给定时器绑定处理函数
signal(SIGALRM, handler);
//让程序每隔1秒打印一点内容,观察到定时器在运行
while (1)
{
printf("main running.... %d\n", getpid());
sleep(1);
}
return 0;
}
微秒定时器:ualarm 函数 微妙定时器是一个循环定时器,微妙定时器只能设置小于 1 秒的时
间,如果>= 1 秒,默认是1 秒(0.999999… 秒)
//调用ualarm函数设置定时器
/*
arg1: 等候多少微妙发送第一次定时器信号
arg2: 之后每隔多少微妙发送定时器信号
所以ualarm也叫循环定时器
注意:该定时器的参数必须小于1秒, 否则不起作用,默认当作一秒处理
*/
//ualarm(500000, 30000); // 0.5, 0.03秒
//注意:该定时器的参数必须小于1秒, 否则不起作用,默认当作一秒处理
//ualarm(3000000, 5000000);
//给定时器绑定处理函数
#include <stdio.h>
#include "header.h"
//ualarm: 微妙定时器
void handler(int signum)
{
printf("rcv: %d\n", signum);
}
int main(int argc, char const *argv[])
{
signal(SIGALRM, handler);
//让程序每隔1秒打印一点内容,观察到定时器在运行
while (1)
{
printf("main running.... %d\n", getpid());
sleep(1);
}
return 0;
}
pause 函数
该函数可以暂定当前进程 基本使用代码:
#include <stdio.h>
#include "header.h"
void handler(int signum)
{
printf("rcv: %d\n", signum);
alarm(5);
}
int main(int argc, char const *argv[])
{
//调用alarm函数设置定时器
alarm(3);
//给定时器绑定处理函数
signal(SIGALRM, handler);
//让程序每隔1秒打印一点内容,观察到定时器在运行
//调用pause函数暂定
pause();
while (1)
{
printf("main running.... %d\n", getpid());
sleep(1);
}
return 0;
}
标签:printf,定时器,进阶,--,编程,int,handler,信号,signum
From: https://blog.csdn.net/weixin_69851948/article/details/145213489