一个信号处理的问题,急

upcuiling 2006-08-11 09:28:03
如何让一个进程在接收到某一信号前死循环的作一件事情,收到信号后就做另外一件事情。
最好能有例子
...全文
282 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
upcuiling 2006-08-12
  • 打赏
  • 举报
回复
在sig_usr1处理函数里面重置了信号,还是不行啊
DanXer 2006-08-12
  • 打赏
  • 举报
回复
你把,下面两行去掉,
sigaddset(&sigzero,SIGUSR1);
sigaddset(&sigzero,SIGUSR2);
linux上现在还没有真正的pselect 所以上面两行作用基本上不会起作用,但可能阻塞信号。

将pselect(0,NULL,NULL,NULL,&ti,&sigzero);的超时参数&ti置为NULL再试试。

另外:用signal处理信号只处理一次,多次触发需要再次安装。只有在bsd4.2的信号语义中,signal才是多次的。所以signal函数不具有移植性。现在没人用了,都使用sigaction,它是posix标准,将struct sigaction::sa_flags置为SA_RESTART来使用多次BSD信号语义。
qdhuxp 2006-08-11
  • 打赏
  • 举报
回复
用3个信号函数
1.signal() //运行函数
2.sigismember() //判断某一信号
3.sigdelset() //删除某一信号
假设你的进程函数action()主函数main()
void action()
{
sigset_t sigset;
while(sigismember(&sigset,SIG1))
{
//做第一件事
if(sigismember(&sigset,SIG2))
{
//做第二件事
sigdelset(&sigset,SIG2);//将第二个信号删除
}
}
}

}
main()
{
// 如果你想让进程死循环作第一件事
signal(SIG1,action);//SIG1是某一个信号,自己设
...
//如果你想让进程死循环作第二件事
signal(SIG2,action);//SIG2是某一个信号,自己设
}

今天刚看了几个信号函数,不知道这样对不对。如果错了不要取笑啊,我刚看了不到10分钟。:)
djfu 2006-08-11
  • 打赏
  • 举报
回复
在sig_usr1处理函数里面你要重置信号

void sig_usr1()
{
// ...
signal(SIGUSR1, sig_usr1);
}

void sig_usr1()
{
// ...
signal(SIGUSR2, sig_usr2);
}
loveisbug 2006-08-11
  • 打赏
  • 举报
回复
upcuiling 2006-08-11
  • 打赏
  • 举报
回复
好像接收了第一个信号,第二个信号,再发第一个信号就接收不到了
upcuiling 2006-08-11
  • 打赏
  • 举报
回复
看了你的提示改把程序改成这样,但是,但我kill -USR2 PID (挂起进程),再执行kill -USR1 PID 还是唤不醒进程阿

int main(void)
{
signal(SIGUSR1,sig_usr1);
signal(SIGUSR2,sig_usr2);
sigset_t sigzero;
sigemptyset(&sigzero);
sigaddset(&sigzero,SIGUSR1);
sigaddset(&sigzero,SIGUSR2);
struct timespec ti;
for(;;)
{

ti.tv_nsec=10*1000; //暂停十秒
int wait=pselect(0,NULL,NULL,NULL,&ti,&sigzero);//等待信号到达
if(wait==-1){//发生错误
continue;
}
}

}
DanXer 2006-08-11
  • 打赏
  • 举报
回复

这是我的一段程序
sigset_t sigzero;
sigemptyset(&sigzero);
/*用下面的方法添加想要同步的信号,保持空集也可以*/
//sigaddset(&sigzero,SIGALRM);
struct timespec ti;
for(;;)
{//消息循环
/*
虽然linux系统现在还没有pselect系统调用,考虑移植性的问题,
我们还是需要pselect代替select.来避免非原子化的变量测试
产生的select的永远等待(现在可能还是会发生)
*/

ti.tv_nsec=10*1000; //暂停十秒
int wait=pselect(0,NULL,NULL,NULL,&ti,&sigzero);//等待信号到达
if(wait==-1){//发生错误
if(errno==EINTR)
{
SYNCLOGINFO(g_fp_infolog,"pselect被信号中断!");
}
else
{
SYNCLOGERROR(g_fp_errlog,"pselect错误,下一次轮询!",errno);
}
continue;
}
}
upcuiling 2006-08-11
  • 打赏
  • 举报
回复
对select使用不熟悉 ,能给个例子看看吗,谢谢
DanXer 2006-08-11
  • 打赏
  • 举报
回复
呵呵,在信号被发送的目标线程里pselect,这时它会停在那里,直到有信号进来pselect才会返回,如果你不想只是停在pselect里,你可以设置一个timeout值给pselect,就可以让它循环做一件事了。是信号还是超时,或是错误你可以通过返回值判断出来,其实select可以做同样的事,只不过,pselect和内核信号框架可以进行同步,保证在pselect调用和你的信号处理函数之间不会产生竞争。
upcuiling 2006-08-11
  • 打赏
  • 举报
回复
我用下面的代码来解决了,可是,当我发送SIGUSR2给进程,让他挂起后,再发SIGUSER1,让他继续写文件就没办法唤醒了,请教了

#include "apue.h"

static void sig_usr1(int);
static void sig_usr2(int);
static int sum;
static int i=0;

int main(void)
{

sum=0;
if(signal(SIGUSR1,sig_usr1)==SIG_ERR)
;
if(signal(SIGUSR2,sig_usr2)==SIG_ERR)
;
while(1)
;
pause();
}

static void sig_usr1(int singno)
{
int to_fd; //要写的目的文件符
int bytes_read=100; //要写的字节数
int bytes_write; //写进的字节数
char buffer[100]; //申请内存空间
char *ptr;
char writepath[40];

sprintf(writepath,"write_%d.txt",i);
ptr=buffer;
if((to_fd=open(writepath,O_WRONLY|O_CREAT|O_APPEND))==-1)
{
fprintf(stderr,"Open %s Error:%s\n",writepath,strerror(errno));
exit(1);
}
while(1)
{

while(bytes_write=write(to_fd,ptr,bytes_read))
{
/* 一个致命错误发生了 */
if((bytes_write==-1)&&(errno!=EINTR))break;
/* 写完了所有读的字节 */
else if(bytes_write==bytes_read) break;
/* 只写了一部分,继续写 */
else if(bytes_write>0)
{
ptr+=bytes_write;
bytes_read-=bytes_write;
}
}
}
}

static void sig_usr2(int singno)
{
//printf("usr2_sum is %d",sum);
i++;
pause();
}

23,223

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧