【发布时间】:2019-11-16 14:03:37
【问题描述】:
编辑: 感谢您迄今为止提出的建议。我更改了程序,现在父级处理了一些信号,但看起来它并没有处理所有这些信号。新代码和结果发布在下面。
编辑2: 我按照建议更改了随机数生成。现在父级只捕获两个信号,但它总是捕获正确的位(最后两个位)。
“不幸的是,我在 C POSIX 方面没有经验,我必须编写一个程序,该程序将接受一个参数(包含二进制数的文件名)并解析该文件。文件中表示的每一位都意味着应该创建一个孩子(每个位专用于一个子级)。
位的值(0 或 1)决定应将哪些信号发送给父级(0 - SIGUSR1, 1 - SIGUSR2)。
子进程应选择一个随机间隔(10-200ms)并向父进程发送适当的信号。
每次新信号到达时,父级应接收信号并打印接收到的最后 5 位。
最后一步是匹配过程 - 父进程检查接收到的信号(分配给 SIGUSR1 或 SIGUSR2 的位),如果匹配,则打印成功。如果没有匹配(无论何时发送错误的位 - 与文件相比),父级从头开始匹配。”
更新版本:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <signal.h>
volatile sig_atomic_t last_signal = 0;
char * str;
char * received;
int count = 0;
#define ERR(source) (fprintf(stderr,"%s:%d\n",__FILE__,__LINE__),\
perror(source),kill(0,SIGKILL),\
exit(EXIT_FAILURE))
void sethandler( void (*f)(int), int sigNo)
{
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = f;
if (-1==sigaction(sigNo, &act, NULL)) ERR("sigaction");
}
char *readFile(char *fileName)
{
FILE *file = fopen(fileName, "r");
char *code;
size_t n = 0;
int c;
if (file == NULL) return NULL; //could not open file
fseek(file, 0, SEEK_END);
long f_size = ftell(file);
fseek(file, 0, SEEK_SET);
code = malloc(f_size);
received = malloc(f_size);
while ((c = fgetc(file)) != EOF) {
code[n++] = (char)c;
}
code[n] = '\0';
return code;
}
void append(char* s, char c)
{
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
}
static void sig_handle(int signum)
{
last_signal = signum;
}
void child_w(int number_of)
{
if(str[number_of] == '0')
{
if (kill(getppid(), SIGUSR1)==0) printf("[SIGUSR1] sent \n");
else
{
printf("ERROR kill. \n");
exit(EXIT_FAILURE);
}
}
if(str[number_of] == '1')
{
if (kill(getppid(), SIGUSR2) == 0) printf("[SIGUSR2] sent \n");
else
{
printf("ERROR kill. \n");
exit(EXIT_FAILURE);
}
}
}
void create_children(int n)
{
pid_t s;
int j = n;
int time = rand() % 191 + 10; // range 10 - 200
struct timespec time_wait = { .tv_sec = 0, .tv_nsec = time * 1000000L };
while(j-->0)
{
nanosleep(&time_wait, NULL);
if((s=fork())<0) ERR("Fork ERROR");
if(!s) {
printf("Child %d started ", j);
printf("with bit: %c \n", str[j]);
child_w(j);
exit(EXIT_SUCCESS);
}
}
}
void parent_w(sigset_t oldmask)
{
int count = 0;
int match = 0;
while(1)
{
last_signal = 0;
while(last_signal != SIGUSR1 && last_signal != SIGUSR2)
{
sigsuspend(&oldmask);
}
printf("\n");
if(last_signal == SIGUSR1)
{
received[count] = '0';
for(int i=0; i<sizeof(received); ++i)
{
printf("%c ", received[i]);
}
count++;
}
else if(last_signal == SIGUSR2)
{
received[count] = '1';
for(int i=0; i<sizeof(received); ++i)
{
printf("%c ", received[i]);
}
count++;
}
printf("\n");
}
}
int main(int argc, char ** argv)
{
char filename[250];
if(argc!=2)
{
printf("Provide one parameter - filename. \n");
return EXIT_FAILURE;
}
strcpy(filename, argv[1]);
str = readFile(filename);
printf("FILE: ");
for(int i=0; i<sizeof(str); ++i)
{
printf("%c ", str[i]);
}
printf("\n");
for(int i=0; i<sizeof(received); ++i)
{
received[i] = '-';
}
sethandler(sig_handle, SIGUSR1);
sethandler(sig_handle, SIGUSR2);
sigset_t mask, oldmask;
sigemptyset(&mask);
sigaddset(&mask, SIGUSR1);
sigaddset(&mask, SIGUSR2);
sigprocmask(SIG_BLOCK, &mask, &oldmask);
create_children(sizeof(str));
parent_w(oldmask);
sigprocmask(SIG_UNBLOCK, &mask, NULL);
free(str);
free(received);
return EXIT_SUCCESS;
}
现在输出总是如下所示:
FILE: 1 0 0 1 1 0 1 0
Child 7 started with bit: 0
[SIGUSR1] sent
Child 6 started with bit: 1
[SIGUSR2] sent
Child 5 started with bit: 0
[SIGUSR1] sent
Child 4 started with bit: 1
[SIGUSR2] sent
Child 3 started with bit: 1
[SIGUSR2] sent
Child 2 started with bit: 0
[SIGUSR1] sent
Child 1 started with bit: 0
[SIGUSR1] sent
0 - - - - - - -
Child 0 started with bit: 1
[SIGUSR2] sent
0 1 - - - - - -
任何进一步的建议将不胜感激:)。
【问题讨论】:
-
将
signal(SIGUSR2, sig_handle2);移动到main()。处理SIGUSR1是因为您只从parent_w执行signal(SIGUSR1, sig_handle1);(并且在循环中,将其从循环中删除),所以只有SIGUSR1处理程序已注册。 -
如果您正确使用
sigaction(),那么您不需要继续重新注册您的处理程序。他们会坚持,如果你指定他们应该这样做。signal()函数不一定是这样,在大多数情况下确实应该避免使用。 -
感谢您的建议。我改变了程序,它工作得更好一点。检查编辑和新代码:)
标签: c arrays linux synchronization posix