【发布时间】:2014-12-22 11:51:11
【问题描述】:
我正在编写一个程序,它从文件中获取 UNIX 命令列表并按顺序执行它们。为了使一切井井有条,我必须初始化每个命令并通过sigwait() 一直等待SIGUSR1。当每条命令都初始化后,就可以执行每条命令了。
用法:> program.c input.txt
但是,SIGUSR1 似乎被反复调用,完全超过了sigwait()。这里发生了什么?我尝试了很多不同的东西,但它最近以this answer 为蓝本。换句话说,我希望在初始化后立即为命令发出信号。我希望在所有命令都完全初始化后解除阻塞
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
void on_sigusr1(int sig)
{
// Note: Normally, it's not safe to call almost all library functions in a
// signal handler, since the signal may have been received in a middle of a
// call to that function.
printf("SIGUSR1 received!\n");
}
int main(int arc, char* argv[])
{
FILE *file;
file = fopen(argv[1] ,"r");
int BUF_SIZE = 100;
char *token;
char buffer[BUF_SIZE];
char programs[BUF_SIZE];
char *commands[BUF_SIZE];
int i = 0;
int counter = 1;
while (fgets(buffer, sizeof buffer, file ) != NULL)
{
strcpy(programs, buffer);
int length = strlen(buffer)-1;
if (buffer[length] == '\n')
{
buffer[length] = '\0';
}
i = 0;
token = strtok(buffer," ");
while(token != NULL)
{
commands[i++] = token;
token = strtok(NULL, " ");
}
commands[i] = 0;
pid_t pids[counter];
// Set a signal handler for SIGUSR1
signal(SIGUSR1, &on_sigusr1);
// At program startup, SIGUSR1 is neither blocked nor pending, so raising it
// will call the signal handler
raise(SIGUSR1);
// Now let's block SIGUSR1
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
sigprocmask(SIG_BLOCK, &sigset, NULL);
// SIGUSR1 is now blocked, raising it will not call the signal handler
printf("About to raise SIGUSR1\n");
raise(SIGUSR1);
printf("After raising SIGUSR1\n");
for(i = 0; i < counter; ++i)
{
pids[i] = fork();
if(pids[i] > 0)
{
printf("Child process %d ready to execute command %s", getpid(), programs);
// SIGUSR1 is now blocked and pending -- this call to sigwait will return
// immediately
int sig;
int result = sigwait(&sigset, &sig);
if(result == 0) {
printf("Child process %d executing command %s", getpid(), programs);
execvp(commands[0], commands);
}
}
}
// All programs have been launched
for(i = 0; i < counter; ++i)
{
wait(&pids[i]);
}
// All programs are waiting to execute
for (i = 0; i < counter; ++i)
{
// SIGUSR1 is now no longer pending (but still blocked). Raise it again and
// unblock it
raise(SIGUSR1);
printf("About to unblock SIGUSR1\n");
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
printf("Unblocked SIGUSR1\n");
}
}
exit(0);
fclose(file);
return 0;
}
更新:尝试将 signal() 更改为 sigaction()。没有变化。
【问题讨论】:
-
"... SIGUSR1 被重复调用" 未调用信号。请问您到底想表达什么?
-
尝试使用
sigaction而不是signal。 -
@alk:我希望在初始化后立即为命令发出信号。我希望在所有命令完全初始化后解除对信号的阻塞。
-
@mnunberg:试过了,没变。
-
您应该在
execvp()之后添加代码以报告错误并退出,以防execvp()返回(又名失败)。就目前而言,如果一个命令失败,它将继续退出其他命令。也许您的on_sigusr1()函数也应该报告 PID?在尝试使多进程系统正常工作时,报告 PID 通常会很有帮助。请注意,fclose(file);和return 0;之前的exit(0);使后两个语句无关紧要。我会删除exit(0);。另外,您能否显示您正在从中读取/执行命令的数据文件的前几行?
标签: c process operating-system signals