linux信号函数
A. linux的kill函数和SIGUSR1信号。
对于这个信号而言,没有信号响应函数的话,进程应该会异常终止,对于系统已有的信号一般都是有默认处理的,具体的我有点记不得了,搜下其实就知道了.我在网上找了下各信号默认处理方式,你看看吧,对你有没有用
信号名称 信号说明 默认处理
SIGABRT 由程序调用 abort时产生该信号。 程序异常结束。 进程终止并且产生core文件
SIGALRM timer到期, 有alarm或者setitimer 进程终止
SIGBUS 总线错误,地址没对齐等。取决于具体硬件。 结束终止并产生core文件
SIGCHLD 进程停止或者终止时,父进程会收到该信号。 忽略该信号
SIGCONT 让停止的进程继续执行 继续执行或者忽略
SIGFPE 算术运算异常,除0等。 进程终止并且产生core文件。
SIGHUP 终端关闭时产生这个信号 进程终止
SIGILL 代码中有非法指令 进程终止并产生core文件
SIGINT 终端输入了中断字符ctrl+c 进程终止
SIGIO 异步I/O,跟SIGPOLL一样。 进程终止
SIGIOT 执行I/O时产生硬件错误 进程终止并且产生core文件
SIGKILL 这个信号用户不能去捕捉它。 进程终止
SIGPIPE 往管道写时,读者已经不在了,或者往一个已断开数据流socket写数据。 进程终止
SIGPOLL 异步I/O,跟SIGIO一样。 进程终止
SIGPROF 有setitimer设置的timer到期引发 。 进程终止
SIGPWR Ups电源切换时 进程终止
SIGQUIT Ctrl+\,不同于SIGINT,这个是会产生core mp文件的。 进程终止并且产生core文件
SIGSEGV 内存非法访问,默认打印出segment fault 进程终止并且产生core文件
SIGSTOP 某个进程停止执行,该信号不能被用户捕捉。 进程暂停执行
SIGSYS 调用操作系统不认识的系统调用。 进程终止并且产生core文件
SIGTERM 有kill函数调用产生。 进程终止
SIGTRAP 有调试器使用,gdb 进程终止并且产生core文件
SIGTSTP Ctrl+z,挂起进程。 进程暂停
SIGTTIN 后台程序要从终端读取成数据时。 进程暂停
SIGTTOU 后台终端要把数据写到终端时。 进程暂停
SIGURG 一些紧急的事件,比如从网络收到带外数据。 忽略
SIGUSR1 用户自定义信号 进程终止
SIGUSR2 用户自定义信号 进程终止
SIGVTALRM 有setitimer产生。 进程终止
B. Linux 环境下的C语言, 关于 kill 发送信号和 signal() 函数, 具体问题在以下代码的注释处
pause()会令目前的进程暂停(进入睡眠状态), 直到被信号(signal)所中断。
当50信号触动了,pause将退出睡眠状态,执行printf和return
C. linux c signal函数
是第二次调用的时候输出的,第一次调用只是绑定了SIGUSR1的信号处理函数,不会进入该处理函数
为什么会有这样的输出呢?
signal函数是将信号与处理函数进行绑定,成功绑定则返回绑定之前的信号处理函数。那么来看看你的代码,第一次调用将sig_fun1绑定,无输出;第二次调用将sig_fun2绑定,也就是把sig_fun1替换下来,并且你还调用了它,参数为30,所以会有那样的输出。
该如何改呢?
其实你并没有涉及到linux的信号处理机制,光绑定是不够的,还需要发信号给它,才能真正进入信号处理过程。给你一个示例代码吧
#include<signal.h>
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
void sig_fun2(int signo)
{
printf("in sig_fun2:%d\n", signo);
}
void sig_fun1(int signo)
{
printf("in sig_fun1:%d\n", signo);
}
int main()
{
unsigned long i;
if (signal(SIGUSR1, sig_fun1) == SIG_ERR)
{
printf("signal fun1 error\n");
exit(1);
}
sleep(15);
(signal(SIGUSR1, sig_fun2))(30);
sleep(15);
printf("done\n");
return 0;
}
/****************************C 代码完,下面是如何运行***************************/
首先编译,假设生成可执行程序为test
然后运行,我用的是后台运行: nohup ./test>output.txt &
注意,这种方法要将输出重定向到文件output.txt(名字无所谓),然后你会看到一个数字,就是pid进程号
最后,在15秒之内发送信号:kill -SIGUSR1 进程号
现在你就可以打开output.txt看输出结果了。如果用sleep的话会被打断,所以只有两个输出加上替换处理函数时的输出共3个,也可以换成 int n=15;while(n--)sleep(1);
-------------------------------------------------------------
怎么样,加分吧
-------------------------------------------------------------
1.我就是想问第二次绑定sig_fun2的时候,调用了第一次绑定的sig_fun1么?
调用了, (signal(SIGUSR1, sig_fun2))(30);就是这一句, signal(SIGUSR1, sig_fun2)是个函数指针,你这样写就是调用它了,但是这和信号处理没关系,写成signal(SIGUSR1, sig_fun2);就可以了
这就是你所说的成功则返回绑定之前的函数???
对
那当时绑定sig_fun1的时候,返回之前的处理函数是什么??
这个就是系统默认的了,比如SIGINT就是你ctrl+c取消程序执行发送的信号,它的处理函数就是结束程序的一系列动作,不过SIGUSR1是留给用户自定义的信号,系统默认应该是啥也不做的一个函数,例如void fun(int signo){},你也可以第一次绑定的时候就调用试试看对不对
2.还有我在看signal函数定义的时候,void(//...)(int) 最后传入的这个int整形参数就是我们自定义sig_fun()中所接收的30么??我看例子里面有的signal(SIGINT,myfunc);也没有带参数啊,搞不懂
是你理解错了,signal函数只是绑定,没涉及到调用绑定函数,不用带参数,信号处理函数不是像你这样调用的。callback回调你知道吧,就是先做好一个函数或过程放着,事件触发的时候才调用。那个30是你用普通函数调用的方式时的参数,跟信号处理一点关系也没有,你用60,70也没半毛钱关系。我猜你是想要调用信号处理函数,然后迷糊了,其实我上面说的“kill -SIGUSR1 进程号”就是触发程序调用该处理函数的信号,这和kill -9 杀死进程一个道理,只不过处理函数不同,结果不一样。ctrl+c也可以用信号的方式发送,kill -2 进程号,或者 kill -SIGINT 进程号
另外,站长团上有产品团购,便宜有保证
D. linux鍑芥暟鏄浠涔堟剰镐濓纻
Linux鍑芥暟鏄浠涔堟剰镐濓纻 鍦↙inux镎崭綔绯荤粺涓锛屽嚱鏁版槸涓绉嶅彲閲岖敤镄勪唬镰佸潡锛屽畠璐熻矗镓ц岀壒瀹氱殑浠诲姟骞惰繑锲炵粨鏋溿侺inux鍑芥暟鍙浠ユ帴鍙楀弬鏁板拰杩斿洖鍊硷纴浠ヤ究鍦ㄧ▼搴忎腑浼犻掍俊鎭鍜屼慨鏀瑰彉閲忋傝繖绉崭唬镰佸岖敤镄勬柟寮忓彲浠ヤ娇绋嫔簭镟村姞妯″潡鍖栵纴骞朵笖鍑忓皯浠g爜镄勯吨澶崭功鍐欍
濡备綍浣跨敤Linux鍑芥暟锛熻佷娇鐢↙inux鍑芥暟锛屾偍闇瑕佺紪鍐欎竴涓鍑芥暟瀹氢箟锛屽寘𨰾鍑芥暟钖岖О銆佸弬鏁板垪琛ㄤ互鍙婅佹墽琛岀殑鎸囦护搴忓垪銆傜劧钖庯纴鎭ㄥ彲浠ュ湪绋嫔簭镄勪富瑕侀儴鍒嗕腑璋幂敤鍑芥暟骞朵紶阃掑弬鏁般侺inux鎻愪緵浜呜稿氩父鐢ㄧ殑鍑芥暟锛屽寘𨰾鏂囦欢I/O銆佺郴缁熻皟鐢ㄥ拰瀛楃︿覆镎崭綔绛夈傛偍鍙浠ヤ娇鐢ㄨ繖浜涙爣鍑嗗嚱鏁帮纴涔熷彲浠ョ紪鍐栾嚜宸辩殑镊瀹氢箟鍑芥暟𨱒ュ疄鐜扮壒瀹氱殑浠诲姟銆
Linux鍑芥暟镄勪紭锷挎槸浠涔堬纻 Linux鍑芥暟镄勪紭锷挎槸璇ュ嚱鏁扮殑浠g爜鍙浠ュ湪绋嫔簭涓澶氭′娇鐢锛屼互鑺傜渷缂栫▼镞堕棿銆傛ゅ栵纴浣跨敤鍑芥暟杩桦彲浠ュ炲姞浠g爜镄勫彲璇绘у拰鍙缁存姢镐с傜敱浜庡畠浠镄勬ā鍧楀寲璁捐★纴瀹冧滑鍙浠ュ緢瀹规槗鍦板垎绫汇佹祴璇曞拰淇鏀广侺inux鍑芥暟杩樻湁锷╀簬闄崭绠绋嫔簭涓镄勯敊璇鐜囷纴锲犱负瀹冧滑鍙浠ョ嫭绔嫔湴杩涜屾祴璇曞拰楠岃瘉銆傚洜姝わ纴Linux鍑芥暟鏄缂栧啓楂樿川閲忓彲闱犵殑绯荤粺镄勫叧阌閮ㄥ垎涔嬩竴銆
E. 濡备綍鍦↙inux涓阃氲繃semget鍜宻emctl鍑芥暟鍒嗛厤骞堕喷鏀句俊鍙烽噺锛
Linux 绯荤粺涓锛屼俊鍙烽噺镄勭$悊阃氲繃 semget 鍜 semctl 杩欎袱涓绯荤粺璋幂敤𨱒ュ畬鎴愶纴瀹冧滑镄勪綔鐢ㄧ被浼间簬 shmget 鍜 shmctl 瀵瑰叡浜鍐呭瓨镄勫勭悊銆傝佷娇鐢ㄤ俊鍙烽噺锛屼綘闇瑕侀栧厛璋幂敤 semget 鍑芥暟锛屼紶鍏ュ弬鏁板寘𨰾淇″彿閲忕粍镄勯敭鍊笺佷俊鍙烽噺镄勬暟閲忎互鍙婃潈闄愭爣璇嗐傞敭鍊肩敤浜庡敮涓镙囱瘑淇″彿閲忕粍锛屽嵆浣胯繘绋嬮鍑猴纴淇″彿閲忎篃浼氩湪绯荤粺涓鎸佷箙瀛桦湪銆傝幏鍙栧凡瀛桦湪镄勪俊鍙烽噺镞讹纴鍙浠ヤ紶鍏0浣滀负缁勫归噺銆
淇″彿閲忕殑鐢熷懡锻ㄦ湡闇瑕佹坠锷ㄧ$悊锛屽綋链钖庝竴涓浣跨敤淇″彿閲忕殑杩涚▼阃鍑烘椂锛岄渶瑕佽皟鐢 semctl 鍑芥暟𨱒ュ垹闄や俊鍙烽噺缁勚傝繖涓鍑芥暟闇瑕佸洓涓鍙傛暟锛氢俊鍙烽噺缁勬爣璇嗙︺佽佹搷浣灭殑淇″彿閲忕紪鍙凤纸鍦ㄨ繖涓渚嫔瓙涓鏄1锛夈佸父閲 IPC_RMID 鍜屼竴涓 union semun 绫诲瀷镄勭粨鏋勪綋锛埚疄闄呮搷浣滀腑蹇界暐锛夈傚垹闄ゆ搷浣滆佹眰璋幂敤钥呬笌淇″彿閲忕粍鍒涘缓钥呮潈闄愮浉钖岋纴鎴栬呮嫢链 root 𨱒冮檺銆备笌 shmget 涓嶅悓锛屽垹闄や俊鍙烽噺缁勪细绔嫔嵆閲婃斁绯荤粺璧勬簮銆
鍦ㄤ唬镰佸眰闱锛屽备唬镰 5.2锛坰em_all_deall.c锛夋墍绀猴纴链変袱涓鍏抽敭鍑芥暟锛氢竴涓鐢ㄤ簬鍒嗛厤浜屽厓淇″彿閲忥纸binary_semaphore_allocation锛夛纴阃氲繃 semget 鍑芥暟銮峰彇鎴栧垱寤猴绂鍙︿竴涓鐢ㄤ簬閲婃斁浜屽厓淇″彿閲忥纸binary_semaphore_deallocate锛夛纴浣跨敤 semctl 鍑芥暟杩涜屽垹闄ゆ搷浣滐纴纭淇濊祫婧愮殑姝g‘閲婃斁銆
鍒嗛厤浜屽厓淇″彿閲忥细 int binary_semaphore_allocation (key_t key, int sem_flags)锛岃繑锲 semget 镄勭粨鏋滐纴濡傛灉闇瑕佸垯鍒涘缓淇″彿閲忋
閲婃斁浜屽厓淇″彿閲忥细 int binary_semaphore_deallocate (int semid)锛岃皟鐢 semctl 鍑芥暟鍒犻櫎淇″彿閲忥纴鍙傛暟鍖呮嫭淇″彿閲忕粍镙囱瘑绗﹀拰甯搁噺 IPC_RMID銆
镓╁𪾢璧勬枡
Linux 鎻愪緵镄勫悇绉岖郴缁熻皟鐢ㄦ潵瀹炵幇涓涓鍏锋湁涓ょ岖姸镐佺殑淇″彿閲忥纸binary semaphore锛夈
F. linux系统上信号发送和信号接收讲解
用于进程间通信,通信机制由操作系统保证,比较稳定。
在linux中可以通过kill -l查看所有信号的类型。
kill -信号类型 进程ID
int kill(pid_t pid, int sig);
入参pid :
pid > 0: 发送信号给指定的进程。
pid = 0: 发送信号给 与调用kill函数进程属于同一进程组的所有进程。
pid < 0: 取|pid|发给对应进程组。
pid = -1:发送给进程有权限发送的系统中所有进程。
sig :信号类型。
返回值 :成功:0;失败:-1 (ID非法,信号非法,普通用户杀init进程等权级问题),设置errno
以OpenHarmony源码为例,应用ANR后,AbilityManagerService会通知应用mp堆栈信息,就是通过信号量做的。
头文件位置 :
include <signal.h>
函数解释 :
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
当接收到指定的信号signum时,就会跳转到参数handler指定的函数执行。其中handler的入参是信号值。
函数原型 :
signum参数指出要捕获的信号类型,act参数指定新的信号处理方式,oldact参数输出先前信号的处理方式(如果不为NULL的话)。
sigaction结构体
sa_handler 信号处理函数
sa_mask 在处理该信号时可以暂时将sa_mask 指定的信号集搁置
sa_flags 指定一组修改信号行为的标志。 它由以下零个或多个的按位或组成
SA_RESETHAND:当调用信号处理函数时,将信号的处理函数重置为缺省值SIG_DFL
SA_RESTART:如果信号中断了进程的某个系统调用,则系统自动启动该系统调用
SA_NODEFER :一般情况下, 当信号处理函数运行时,内核将阻塞该给定信号。但是如果设置了 SA_NODEFER标记, 那么在该信号处理函数运行时,内核将不会阻塞该信号
sa_restorer 是一个替代的信号处理程序,当设置SA_SIGINFO时才会用它。
相关函数
int sigemptyset( sigset_t *set);
sigemptyset()用来将参数set信号集初始化并清空。
执行成功则返回0,如果有错误则返回-1。
完整示例