linux的signal
⑴ linux环境下使用signal函数进行进程间通信的问题
测试了一下,三个进程都会收到SIGINT信号。
原程序中,child1, child2都收到SIGINT信号,调用stop(), 之后被唤醒,打印"child process ... is killed by parent!",事实上kill这两个child的不是parent,是它们自己的SIGINT。
放到①处,child1收到SIGINT信号,默认的行为是把自己杀了,当然也来不及打印任何东西了。child2收到SIGINT信号,打断waiting(),打印"child process 2 ...",然后退出。杀死它的也不是SIGUSR2信号。
放到②处,child1, child2收到SIGINT信号,默认的行为是立即把自己杀了,也来不及打印任何东西了。
测试方法:
// 打印谁执行、被什么信号打断
static void stop(int signal) {
printf("stop %d by signal %d\n", getpid(), signal);
wait_mark=0;
}
// 在parent进程中,打印各进程id
printf("parent %d, child1 %d, child2 %d\n",getpid(),p1,p2);
如果让parent成为杀死child的兇手,可以在child1,child2中加入:
signal(SIGINT, keep_me_alive);
// 不理睬SIGINT信号
static void keep_me_alive(int signal) {
}
这时打印结果就一样了
⑵ linux 中的signal 函数
这是个函数指针,
void ( *func )( int )是一个接受一个int型参数,不返回的函数的指针;
比如:
void F( int a ) { print( "%d", a ); }
void ( *func )( int ) = F;
func( 3 ); // 调用F函数输出3
作为函数参数的函数指针有一个专门的名称叫做回调,你可以把任意满足回调函数参数特征标的函数地址作为参数传给signal。
在这里因为signal对于sig参数可以指定用户自定义的信号处理函数,所以你可以把你要处理的这个sig的函数地址作为参数传给signal,那么系统接收到对应sig的时候就会通过你传进去的地址调用你的这个函数。
⑶ 怎么查看 linux signal
有个current指针指向当前正在运行的进程,你一个ctrl+c后由产生一个信号,主要是current ,看看linux内核中的进程调度
⑷ linux下进程通信中signal和message queue的区别
信号一般是发送给一个正在执行中的进程的系统级别的中断。但是有些系统级别的调用不会被信号中断。所以,你可以从一个进程给另一个进程发送一个信号(比如Kill
进程号,读取man
page)去实现进程间的通信;
消息对列是由操作系统提供的机制,负责进程之间消息类型化通信;
使用信号量,如果信号自己没有足够容量包含信息,需要其他共享资源去保存信息。如果想发送一个字符串消息,你需要将一个字符串保存到另外一个进程能够获取到字符串地方,然后发送信号告诉该进程这个消息已经准备好了。
如果通过消息队列发送消息,系统不会中断进程让进程知道,进程必须主动检查给自己的消息。如果你不使用select()系统去检查自己的消息,你就必须一直等待。
这是使用消息对列最大的问题。
消息队列是类型化的,你可以使用这种类型去发送/接收的消息。
信号不会被计数,仅仅会做个简单的标记。
当多个信号到达并被阻塞时,系统仅仅标记有信号到达,不会告诉进程有多少个信号到,所以在编程时要留意这个问题。
⑸ 关于linux signal的问题
也就是说,当GPS数据准备好后会发送signal给你们自己写的平台软件,相当于请求刷屏幕,然后平台软件执行刷屏幕操作,这两个之间需要一个同步关系就是说,当有请求后我才去刷屏幕操作。
这种情况不是因为平台进程接受不到signal,而是收到了signal信号而且正确执行了sem_post操作(你可以在signal handler中加入打印调试语句看看),因为你的刷屏幕操作线程执行时间太长了,导致连续执行好几次屏幕操作,这是种恶性循环(因为gps软件每次数据准备好就发送个signal,而你的 signal在每次捕捉到signal后就执行一次sem_post,然而你的刷屏幕操作时间太长了当执行完一次刷屏幕操作后再次调用sem_wait的时候已经有多个信号量资源了也就是消费跟不上生产,信号量post次数比wait次数多)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
sem_t lock;
int gps_data = 0;
/* fflush screen thread */
void *gps_data_process (void *arg)
{
while (1)
{
/* wait gps data is ready */
/* second run sem_wait will by more semaphore it will not block */
sem_wait(&lock);
/* ok data is ready */
printf("Data is [%d]\n", gps_data);
/* simulate a long procees time */
sleep(100);
}
}
/* SIGUSR1 handler */
void gps_data_request(int sig)
{
if (sig == SIGUSR1)
{
/* ok gps data is ready so request process */
sem_post(&lock);
}
}
int main(int argc, char **argv)
{
pthread_t tid;
struct sigaction action;
/* initialize semaphore */
if (sem_init(&lock, 0, 0) == -1)
{
perror("sem_init");
exit(1);
}
action.sa_handler = gps_data_request;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
/* caught signal SIGUSR1 */
if (sigaction(SIGUSR1, &action, NULL))
{
perror("sigaction");
exit(1);
}
/* create a thread */
if (pthread_create(&tid, NULL, gps_data_process, NULL) == -1)
{
perror("pthread_create");
exit(1);
}
while (1)
{
printf("[GPS]>>>");
/* gps get data ready */
scanf("%d", &gps_data);
if (gps_data)
{
/* simulate gps program send signal to platform process */
raise(SIGUSR1);
}
sleep(1);
}
return 0;
}
⑹ 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 进程号
另外,站长团上有产品团购,便宜有保证
⑺ linux signal(SIGINT,SIG_IGN);大概解释一下
signal,此函数相对简单一些,给定一个信号,给出信号处理函数则可,当然,函数简单,其功能也相对简单许多,简单给出个函数例子如下:
#include<signal.h>
#include<stdio.h>
#include<unistd.h>
voidouch(intsig)
{
printf("Igotsignal%d ",sig);
//(void)signal(SIGINT,SIG_DFL);
//(void)signal(SIGINT,ouch);
}
intmain()
{
(void)signal(SIGINT,ouch);
while(1)
{
printf("helloworld... ");
sleep(1);
}
}
当然,实际运用中,需要对不同到signal设定不同的到信号处理函数,SIG_IGN忽略/SIG_DFL默认,这俩宏也可以作为信号处理函数。同时SIGSTOP/SIGKILL这俩信号无法捕获和忽略。注意,经过实验发现,signal函数也会堵塞当前正在处理的signal,但是没有办法阻塞其它signal,比如正在处理SIG_INT,再来一个SIG_INT则会堵塞,但是来SIG_QUIT则会被其中断,如果SIG_QUIT有处理,则需要等待SIG_QUIT处理完了,SIG_INT才会接着刚才处理。
⑻ linux中的signal怎么使用
signal函数的定义很复杂,但是它的用法还是比较简单的,你记住它的两个参数就可以了。signal有两个参数sig和func,signal这个函数是用来接收信号并处理的,所以sig参数表示将要处理哪种类型的信号,而func参数是一个函数指针,用来指定信号的处理函数,也就是当程序接收到sig那个类型的信号后,就会调用func指针指向的函数。func指针的原型是:
void (*func) (int)
所以信号的处理函数必须是一个返回void,只有一个int类型参数的函数。
比如如果程序需要处理Ctrl+C组合键产生的信号,就可以这样使用signal函数:
(void) signal(SIGINT, myfunc);
而myfunc函数可以这样定义:
void myfunc(int sig)
{
printf("Hello, the signal is %d\n", sig);
// 因为现在处理的是Ctrl+C信号,所以下面要
// 恢复程序对Ctrl+C的默认反应
(void) signal(SIGINT, SIG_DFL);
}
⑼ linux signal 11 是什么意思
通过kill -l 可以查看信号列表,11 是段错误
$ kill -l
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 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