百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

Linux进程间通信——信号 卖出股票的信号

liebian365 2024-10-30 04:48 28 浏览 0 评论

概念

什么是信号?

  • 信号是linux系统中一种常用的通信机制,A给B发送信号,B在收到信号之前执行自己的代码,收到信号后,不管执行什么程序,都暂停运行,去处理信号,处理完毕后再继续执行原来的程序,是一种软中断。

特点

  • 由于信号是通过软件方法实现的,具有很强的延时性,对用户来讲,时间非常短,不易察觉
  • 每个进程收到的所有信号,都是由内核负责发送,内核处理

与信号相关的事件或者名词

产生信号的基本方法

  • 系统调用当前进程的某些函数
  • 通过命令产生,如kill指令
  • 硬件异常、段错误、内存出错、总线错误
  • 软件条件产生,如alarm定时器
  • 硬件产生,如ctrl+c按键

信号分类及信号一览表

1.可靠信号与不可靠信号

  • 不可靠信号
    Linux信号机制基本上是从Unix系统中继承过来的。早期Unix系统中的信号机制比较简单和原始,信号值小于SIGRTMIN的信号都是不可靠信号,它的主要问题是信号可能丢失。
  • 可靠信号
    随着时间的发展,实践证明了有必要对信号的原始机制加以改进和扩充。由于原来定义的信号已有许多应用,不好再做改动,最终只好又新增加了一些信号,并在一开始就把它们定义为可靠信号,这些信号支持排队,不会丢失

2.指令kill -l 查看所有信号

  • 信号的名称是在头文件 <signal.h>里定义的
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN
+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
  • Linux提供两个特殊信号:9号和19号信号,无法修改,提供终止进程的手段
  • 写信号时最好使用信号宏名称,因为不同系统下宏的数值可能是不同的,如下有些信号宏可能有多个数值

递达

从信号产生,会先发送给内核,通过内核处理再发送到进程,进程再处理信号这一过程称为递达

未决信号集

从信号产生,还未递达至进程,信号没有被处理掉,这过程中会有一个未决信号集存贮这些信号

阻塞信号集

也叫做信号屏蔽字,每个进程都有一个用来描述哪些信号递送到进程时将被阻塞的信号集,该信号集中的所有信号在递送到进程后都将被阻塞。


假设发送第三个信号,若阻塞信号集第三位为1,那么进程就不会收到该信号,因此未决信号集中第三位将保持状态为1

Linuxc/c++服务器开发高阶视频,电子书学习资料后台私信【架构】获取

内容包括C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,MongoDB,ZK,流媒体,P2P,K8S,Docker,TCP/IP,协程,DPDK多个高级知识点

信号处理方式

  • 系统默认动作,例如ctrl+c将进程杀死
  • 忽略(丢弃)该信号,就象没有收到该信号似的继续运行
  • 捕捉信号,自定义动作

信号相关函数

头文件<signal.h>

  • signal函数
    函数原型:
    typedef void (*sighandler_t)(int);//返回类型为空的函数指针,整型参数
    sighandler_t signal(int signum, sighandler_t handler)
    功能:接收某个信号sig(第一个参数),使程序接收到信号时执行对应函数func(第二个参数),func这个函数必须有一个int类型的参数(即接收到的信号)
    func也可以是下面两个特殊值:
    SIG_IGN 屏蔽该信号
    SIG_DFL 恢复默认行为
  • int kill(pid_t pid, int sig);
    功能:给指定进程发送信号(不一定杀死),第一个参数是进程ID,第二个参数是发送信号的类别,
    返回值:成功返回0, 失败返回-1
  • int sigemptyset(sigset_t *set);
    功能:将某个信号集清0
    返回值:成功返回0, 失败返回-1
  • int sigfillset(sigset_t *set);
    功能:将某个信号置1
    返回值:成功返回0, 失败返回-1
  • int sigaddset(sigset_t *set, int signo);
    功能:将某个信号加入到信号集中
    返回值:成功返回0, 失败返回-1
  • int sigdelset(sigset_t *set, int signo);
    功能:用来将参数signo信号从参数set信号集里删除。
    返回值:成功则返回0,如果有错误则为-1。
  • int sigismember(const sigset_t *set, int signo);
    功能:用来测试参数signo信号是否已加入至参数set信号集里。
    返回值:如果信号集里已有该信号则返回1,否则返回0。错误则为-1
  • int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
    功能:读取或更改进程的信号屏蔽字。
    返回值:若成功则为0,若出错则为-1


参数how的含义

  • int sigpending(sigset_t *set);
    功能: sigpending读取当前进程的未决信号集,通过set参数传出。
    返回值:若成功则为0,若出错则为-1
  • void abort(void);
    头文件:<stdlib.h>
    功能:向进程发送sigabort信号,默认情况下进程会异常退出,当然可定义自己的信号处理函数。
    说明:即使sigabort被进程设置为阻塞信号,调用abort()后,sigabort仍然能被进程接收。该函数无返回值

讲了这么多,做个例子,主要实现的功能是:打印当前进程未决信号集,并测试屏蔽信号

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/time.h>

void printf_ped(sigset_t* ped)
{
	int i;
	for (i = 0; i < 32; i++)
	{
		if (sigismember(ped, i) == 1)
		{
			putchar('1');	
		}
		else
		{
			putchar('0');
		}
	}
	printf("\n");
}

int main(void)
{
	sigset_t myset, oldset, ped_set;

	sigemptyset(&myset);//清空信号集为0
	sigaddset(&myset, SIGQUIT);//添加信号到信号集中

	sigprocmask(SIG_BLOCK, &myset, &oldset); //设置进程的信号屏蔽字

	while (1)
	{
		sigpending(&ped_set);//读取未决信号集到ped_set中
		printf_ped(&ped_set);//打印打印未决信号集
		sleep(3);
	}
	return 0;
}

运行结果如下


一开始没有产生信号 未决信号集都为0,当我们按下crtl+\时产生3号信号,但是由于我们屏蔽了3号信号,未决信号集中第三位一直为1,表示该信号还未被处理

定时器相关函数

头文件 #include <sys/time.h>

alarm函数

  • 每个进程只有一个alarm
  • 无论进程处于何种状态下,定时器都在计时

函数原型:
unsigned int alarm(unsigned int seconds);

功能:专门为sigalrm信号而设,在指定的时间seconds秒后,将向进程本身发送sigalrm信号

返回值:如果调用alarm()前,进程中已经设置了闹钟时间,则返回上一个闹钟时间的剩余时间,否则返回0

说明:进程调用alarm后,任何以前的alarm()调用都将无效

setitimer函数

函数原型:
int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);

参数:
第一个参数 which指定定时器类型
第二个参数 结构itimerval的一个实例
第三个参数 可不做处理,old_value一般设为NULL

结构体类型如下

struct itimerval
 {
        struct timeval it_interval; /* 下一次的取值 */
        struct timeval it_value; /* 本次的设定值 */
};

struct timeval 
{
        long tv_sec; /* 秒 */
        long tv_usec; /* 微秒,1秒 = 1000000 微秒*/
};

功能:这个函数可以周期性计时,定时器将it_value递减到0时,产生一个信号,并将it_value的值设定为it_interval的值,然后重新开始计时,如此往复,若it_interval为0则定时器停止。参数ovalue如果不为空,则其中保留的是上次调用设定的值

返回值:成功返回0,失败返回-1

定时器类型:

itimer_real: 按实际时间计时(系统时间+用户时间+等待时间),经过指定的时间后,内核将发送SIGALRM信号给本进程
itimer_virtual :只计算进程占用cpu的时间,经过指定的时间后,内核将发送SIGVTALRM信号给本进程
itimer_prof :计算占用cpu及执行系统调用的时间,经过指定的时间后,内核将发送SIGPROF信号给本进程

写个例子,每3秒打印一次hello world

#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <signal.h>


void myfun(int signo)
{
	printf("hello world\n");
}

int main()
{
	struct itimerval it, oldit;
	int ret;

	signal(SIGALRM, myfun);

	//本次设定值
	it.it_value.tv_sec = 3;
	it.it_value.tv_usec = 0;

	//下次设定值
	it.it_interval.tv_sec = 3;
	it.it_interval.tv_usec = 0;

	ret = setitimer(ITIMER_REAL, &it, &oldit);
	if (ret == -1)
	{
		printf("error\n");
		exit(1);
	}

	while (1);
	return 0;
}

运行结果

相关推荐

精品博文嵌入式6410中蓝牙的使用

BluetoothUSB适配器拥有一个BluetoothCSR芯片组,并使用USB传输器来传输HCI数据分组。因此,LinuxUSB层、BlueZUSB传输器驱动程序以及B...

win10跟这台计算机连接的前一个usb设备工作不正常怎么办?

前几天小编闲来无事就跑到网站底下查看粉丝朋友给小编我留言询问的问题,还真的就给小编看到一个问题,那就是win10跟这台计算机连接的一个usb设备运行不正常怎么办,其实这个问题的解决方法时十分简单的,接...

制作成本上千元的键盘,厉害在哪?

这是稚晖君亲自写的开源资料!下方超长超详细教程预警!!全文导航:项目简介、项目原理说明、硬件说明、软件说明项目简介瀚文智能键盘是一把我为自己设计的——多功能、模块化机械键盘。键盘使用模块化设计。左侧的...

E-Marker芯片,USB数据线的“性能中枢”?

根据线缆行业的研究数据,在2019年搭载Type-C接口的设备出货量已达到20亿台,其中80%的笔记本电脑和台式电脑采用Type-C接口,50%的智能手机和平板电脑也使用Type-C接口。我们都知道,...

ZQWL-USBCANFD二次开发通讯协议V1.04

修订历史:1.功能介绍1.1型号说明本文档适用以下型号:  ZQWL-CAN(FD)系列产品,USB通讯采用CDC类实现,可以在PC机上虚拟出一个串口,串口参数N,8,1格式,波特率可以根据需要设置(...

win10系统无法识别usb设备怎么办(win10不能识别usb)

从驱动入手,那么win10系统无法识别usb设备怎么办呢?今天就为大家分享win10系统无法识别usb设备的解决方法。1、右键选择设备管理器,如图:  2、点击更新驱动程序,如图:  3、选择浏览...

微软七月Win8.1可选补丁有内涵,含大量修复

IT之家(www.ithome.com):微软七月Win8.1可选补丁有内涵,含大量修复昨日,微软如期为Win7、Win8.1发布7月份安全更新,累计为6枚安全补丁,分别修复总计29枚安全漏洞,其中2...

如何从零开始做一个 USB 键盘?(怎么制作usb)

分两种情况:1、做一个真正的USB键盘,这种设计基本上不涉及大量的软件编码。2、做一个模拟的USB键盘,实际上可以没有按键功能,这种的需要考虑大量的软件编码,实际上是一个单片机。第一种设计:买现成的U...

电脑识别U盘失败?5个实用小技巧,让你轻松搞定USB识别难题

电脑识别U盘失败?5个实用小技巧,让你轻松搞定USB识别难题注意:有些方法会清除USB设备里的数据,请谨慎操作,如果不想丢失数据,可以先连接到其他电脑,看能否将数据复制出来,或者用一些数据恢复软件去扫...

未知usb设备设备描述符请求失败怎么解决

出现未知daousb设备设备描述符请求失du败解决办zhi法如下:1、按下Windows+R打开【运行】;2、在版本运行的权限输入框中输入:services.msc按下回车键打开【服务】;2、在服务...

读《飘》47章20(飘每章概括)

AndAhwouldn'tleaveMissEllen'sgrandchildrenfornotrashystep-patobringup,never.Here,Ah...

英翻中 消失的过去 37(消失的英文怎么说?)

翻译(三十七):消失的过去/茱迪o皮考特VanishingActs/JodiPicoult”我能做什么?“直到听到了狄利亚轻柔的声音,我才意识到她已经在厨房里站了好一会儿了。当她说话的时候,...

RabbitMQ 延迟消息实战(rabbitmq如何保证消息不被重复消费)

现实生活中有一些场景需要延迟或在特定时间发送消息,例如智能热水器需要30分钟后打开,未支付的订单或发送短信、电子邮件和推送通知下午2:00开始的促销活动。RabbitMQ本身没有直接支持延迟...

Java对象拷贝原理剖析及最佳实践(java对象拷贝方法)

作者:宁海翔1前言对象拷贝,是我们在开发过程中,绕不开的过程,既存在于Po、Dto、Do、Vo各个表现层数据的转换,也存在于系统交互如序列化、反序列化。Java对象拷贝分为深拷贝和浅拷贝,目前常用的...

如何将 Qt 3D 渲染与 Qt Quick 2D 元素结合创建太阳系行星元素?

Qt组件推荐:QtitanRibbon:遵循MicrosoftRibbonUIParadigmforQt技术的RibbonUI组件,致力于为Windows、Linux和MacOSX提...

取消回复欢迎 发表评论: