C POSIX子级根据文件内容发送信号,父级将接收到的信号与文件匹配

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C POSIX子级根据文件内容发送信号,父级将接收到的信号与文件匹配相关的知识,希望对你有一定的参考价值。

[不幸的是,我没有C POSIX的经验,我必须编写一个程序,该程序将接受一个参数(包含二进制数的文件名)并解析该文件。文件中指示的每一位意味着应创建一个孩子(每一位专用于一个孩子)。位的值(0或1)决定应将哪些信号发送到父级(0-SIGUSR1,1-SIGUSR2)。子进程应选择一个随机间隔(10-200ms),并向父进程发送适当的信号。

父母应接收信号,并在每次收到新信号时打印接收到的最后5位。

最后一步是匹配过程-父级检查接收到的信号(分配给SIGUSR1或SIGUSR2的位),如果匹配,则打印SUCCESS。如果没有匹配项(每当发送错误位-与文件进行比较),父级将从头开始匹配。

到目前为止我所做的:

#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>

char * str; // the array consisting of bits from the file
char * received; //array of the parent receiving the signals
int count = 0;
//Error macro
#define ERR(source) (fprintf(stderr,"%s:%d
",__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");
}

//Reading file char by char and returning allocated char array
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] = '';

    return code;
}
// Append the character to the received array
void append(char* s, char c)
{
        int len = strlen(s);
        s[len] = c;
        s[len+1] = '';
}
// SIGUSR1 handler. I tried to implement simple counter to check if the parent is receiving the signals, then proceed to printing last 5 bits received. Unfortunately this part seems to not work at all.
static void sig_handle1(int signum)
{
  signal(SIGUSR1, sig_handle1);
  count++;
  printf("%d 
", count);

}
// Handler for SIGUSR2 - same as handler for SIGUSR1
static void sig_handle2(int signum)
{
  signal(SIGUSR2, sig_handle2);
  count++;
  printf("%d 
", count);

}
// Child function - set the random interval, wait and then send the appropriate signal to the parent
void child_w(int number_of)
{
  srand(time(NULL)*getpid());
  int time = rand()%100 + 10;
  struct timespec time_wait = {time/1000, 0};
  nanosleep(&time_wait, NULL);

    if(str[number_of] == '0')
    {
      if (kill(getppid(), SIGUSR1)==0) printf("[SIGUSR1] sent 
");
      else
      {
        printf("ERROR kill. 
");
        exit(EXIT_FAILURE);
      }
    }

    if(str[number_of] == '1')
    {
      if (kill(getppid(), SIGUSR2) == 0) printf("[SIGUSR2] sent 
");
      else
      {
        printf("ERROR kill. 
");
        exit(EXIT_FAILURE);
      }
    }
}
// Function which will create children (number of children = number of bits in the file)
void create_children(int n)
{
  pid_t s;
  int j = n;
       while(j-->0)
       {
         if((s=fork())<0) ERR("Fork ERROR");
         if(!s) {
                  printf("Child %d started ", j);
                  printf("with bit: %c 
", str[j]);
                  child_w(j);
                 //if(j==1) kill(getppid(), SIGUSR2);
                 exit(EXIT_SUCCESS);
         }
       }
}
// Parent function to check the received signals
void parent_w()
{
  while(1)
  {
    signal(SIGUSR1, sig_handle1);

  }


}

int main(int argc, char ** argv)
{
  char filename[250];

  if(argc!=2)
  {
    printf("Provide one parameter - filename. 
");
    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("
");

  sethandler(SIG_IGN,SIGUSR1);
  sethandler(SIG_IGN,SIGUSR2);

  create_children(sizeof(str)-1);
  parent_w();


  free(str);
  free(received);

  return EXIT_SUCCESS;
}

我得到的输出:

FILE: 1 0 0 1 1 0 1 

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 
1 
Child 0 started with bit: 1 
[SIGUSR2] sent 

文件已正确解析。创建了适当数量的子代,似乎他们向父代发送了适当的信号。

问题在于接收信号的父级处理(似乎只有count = 1显示在中间的某处)。显然,如果没有父母的适当信号处理,我将无法尝试执行最后一步-尽管如此,我真的不知道如何在不编写过于复杂的内容的情况下制作此类东西。

任何建议/帮助将不胜感激。

答案

首先,好的代码。

第二:

  • 手册页是您的朋友。 man signal
  • signal() registers信号处理程序。因此,在signal(SIGUSR1, some_function)之后,将在接收到信号后执行功能some_function
  • 从信号处理程序调用Removoe signal()(为什么要从处理程序内部重新注册相同的处理程序?它已经是此信号的处理程序。)
  • 从父级的循环中删除signal()调用。只需注册一次功能就可以了。
  • 您的sethandler功能与signal相同。

经过一些修复:

#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>

char * str; // the array consisting of bits from the file
char * received; //array of the parent receiving the signals
int count = 0;
//Error macro
#define ERR(source) (fprintf(stderr,"%s:%d
",__FILE__,__LINE__),
                     perror(source),exit(EXIT_FAILURE))

//Reading file char by char and returning allocated char array
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] = '';

    return code;
}
// Append the character to the received array
void append(char* s, char c)
{
        int len = strlen(s);
        s[len] = c;
        s[len+1] = '';
}
// SIGUSR1 handler. I tried to implement simple counter to check if the parent is receiving the signals, then proceed to printing last 5 bits received. Unfortunately this part seems to not work at all.
static void sig_handle1(int signum) {
  count++;
  printf("%s %d 
", __func__, count);

}
// Handler for SIGUSR2 - same as handler for SIGUSR1
static void sig_handle2(int signum) {
  count++;
  printf("%s %d 
", __func__, count);

}
// Child function - set the random interval, wait and then send the appropriate signal to the parent
void child_w(int number_of)
{
  srand(time(NULL)*getpid());
  int time = rand()%100 + 10;
  struct timespec time_wait = {time/1000, 0};
  nanosleep(&time_wait, NULL);

    if(str[number_of] == '0')
    {
      if (kill(getppid(), SIGUSR1)==0) printf("[SIGUSR1] sent 
");
      else
      {
        printf("ERROR kill. 
");
        exit(EXIT_FAILURE);
      }
    }

    if(str[number_of] == '1')
    {
      if (kill(getppid(), SIGUSR2) == 0) printf("[SIGUSR2] sent 
");
      else
      {
        printf("ERROR kill. 
");
        exit(EXIT_FAILURE);
      }
    }
}
// Function which will create children (number of children = number of bits in the file)
void create_children(int n)
{
  pid_t s;
  int j = n;
       while(j-->0)
       {
         if((s=fork())<0) ERR("Fork ERROR");
         if(!s) {
                  printf("Child %d started ", j);
                  printf("with bit: %c 
", str[j]);
                  child_w(j);
                 //if(j==1) kill(getppid(), SIGUSR2);
                 exit(EXIT_SUCCESS);
         }
       }
}
// Parent function to check the received signals
void parent_w()
{
        signal(SIGUSR1, sig_handle1);
        signal(SIGUSR2, sig_handle2);
  while(1)
  {
          pause();

  }
}

int main(int argc, char ** argv)
{
  char filename[250];

  if(argc!=2)
  {
    printf("Provide one parameter - filename. 
");
    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("
");

  create_children(sizeof(str)-1);
  parent_w();


  free(str);
  free(received);

  return EXIT_SUCCESS;
}

以上是关于C POSIX子级根据文件内容发送信号,父级将接收到的信号与文件匹配的主要内容,如果未能解决你的问题,请参考以下文章

通过共享内存和管道的 IPC 给出分段错误:C 中的 11

POSIX 信号量父信号量值不受影响

C++ 根据父级指针删除子级

El-Tree 扩展 父级选中可以影响子级,子级不能影响父级

执行时间的准确变化

js实现多级复选框的交互