C 向所有线程发送信号

C 向所有线程发送信号,c,linux,multithreading,posix,C,Linux,Multithreading,Posix,我试图创建简单的信号处理——比如说终止进程。我的程序中有三个独立的线程+主线程 问题是调用该信号会导致当前线程终止,而其他线程仍在运行 如何将信号发送到其余线程?在发送这些信号时,如何区分这些信号 顺便说一下,我这里必须使用FIFO 以下是到目前为止我得到的信息: #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <unistd.h> #include <

我试图创建简单的信号处理——比如说终止进程。我的程序中有三个独立的线程+主线程

问题是调用该信号会导致当前线程终止,而其他线程仍在运行

如何将信号发送到其余线程?在发送这些信号时,如何区分这些信号

顺便说一下,我这里必须使用FIFO

以下是到目前为止我得到的信息:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/stat.h>
#include <pthread.h>
#include <string.h>
#include <signal.h>

int first[2];
int second[2];

#define FIFO_FILE "tmp/myfifo"

void *input(void *ptr)
{
   char str[100], fifo[100];
   int length;
   FILE *fp;

   while(1)
   {
      fp = fopen(FIFO_FILE, "r");
      fgets(fifo, 100, fp);
      if(fifo == "s1")
      {
         printf("SIGNAL 1!!!");
         exit(1);
      }

      printf("Enter the message: ");
      fflush(stdout);
      length = read(STDIN_FILENO, str, sizeof(str));

      if(str[0] == ';')
         exit(2);

      if(length <= 0)
      {
         if(length == -1)
            perror("read");
         close(first[1]);
         exit(2);
      }

      if(write(first[1], str, length) != length)
      {
         perror("write");
         exit(2);
      }
   }
}

void *countChars(void *ptr)
{
   char str[100], fifo[100];
   int length, count = 0;
   FILE *fp;

   while(1)
   {
      fp = fopen(FIFO_FILE, "r");
      fgets(fifo, 100, fp);
      if(fifo == "s1")
      {
         printf("SIGNAL 1!!!");
         exit(1);
      }

      length = read(first[0], str, sizeof(str));
      if(length <= 0)
      {
         if(length == -1)
            perror("read");
         close(first[0]);
         close(second[1]);
         exit(2);
      }
      if(write(STDOUT_FILENO, str, length) != length)
      {
         perror("write");
         exit(2);
      }

      while(str[count] != '\n') count++;

      write(second[1], &count, sizeof(count));

      count = 0;
   }
}

void *output(void *ptr)
{
   int length, count = 0;
   char fifo[100];
   FILE *fp;

   while(1)
   {
      fp = fopen(FIFO_FILE, "r");
      fgets(fifo, 100, fp);
      if(fifo == "s1")
      {
         printf("SIGNAL 1!!!");
         exit(1);
      }

      length = read(second[0], &count, sizeof(count));
      if(length < sizeof(count))
      {
         close(second[0]);
         exit(2);
      }

      printf("Number of characters: %d\n", count); 
   }
}

void s1_handler(int signo)
{
   FILE *fp;

   if((fp = fopen(FIFO_FILE, "wb")) == NULL)
   {
      perror("fopen");
      exit(2);
   }

   fputs("s1", fp);

   fclose(fp);
}

int main()
{
   pthread_t t1, t2, t3;

   if(pipe(first) == -1)
   {
      printf("First pipe error");
      exit(1);
   }

   if(pipe(second) == -1)
   {
      printf("Second pipe error");
      exit(1);
   }

   pthread_create(&t1, NULL, input, NULL);
   pthread_create(&t2, NULL, countChars, NULL);
   pthread_create(&t3, NULL, output, NULL);

   if(signal(SIGINT, s1_handler) == SIG_ERR)
   {
      printf("Cant catch SIGINT\n");
   }

   pthread_join(t1, NULL);
   pthread_join(t2, NULL);
   pthread_join(t3, NULL);

   return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int-first[2];
整数秒[2];
#定义FIFO_文件“tmp/myfifo”
无效*输入(无效*ptr)
{
字符str[100],fifo[100];
整数长度;
文件*fp;
而(1)
{
fp=fopen(FIFO_文件,“r”);
fgets(先进先出、100、fp);
如果(先进先出=“s1”)
{
printf(“信号1!!!”);
出口(1);
}
printf(“输入消息:”);
fflush(stdout);
长度=读取(标准文件号、str、sizeof(str));
如果(str[0]=';')
出口(2);

如果(长度只有一条螺纹收到信号!哪一条?请参阅以下引用的详细信息:

哪个线程接收信号

这是最有趣的问题。有两种情况:

过程定向信号(使用kill(2)等函数发送至PID)。 线程有其单独的信号掩码,可以使用pthread_sigmask(2)像sigprocmask(2)一样对其进行操作,因此,此类信号不会传递给已阻止此信号的线程。它将在该信号未阻止的情况下传递给进程中的一个线程。未指定哪个线程将获得该信号。如果所有线程都阻止了该信号,则该信号将在每个进程队列中排队。如果没有为该信号和默认操作定义信号处理程序是在倾倒或不倾倒堆芯的情况下终止工艺,整个工艺终止。 线程定向信号。有一个特殊函数可以向特定线程发送信号:pthread_kill(2)。它可以用于从一个线程向另一个线程(或自身)发送信号。这样,信号将被传递或排队等待特定线程。操作系统(如SIGSEGV)也会生成每个线程定向的信号。如果没有为默认操作是终止进程的信号定义信号处理程序,则线程定向的信号会终止整个进程

您的程序中有很多(概念上的)错误

信号:标准信号(即像SIGINT这样的非实时信号)不排队。您的进程将只接收一个信号,并且任何其他信号(相同类型)都将被丢弃,直到以某种方式处理已发送的信号。信号(无论如何,大多数)将作为一个整体传递给进程。如果程序没有采取其他操作,信号将传递给进程中的任意线程。您可以使用
pthread\u kill
将捕获的信号重新发送给其他线程,但这将要求您通过例如,使用一个TID的全局表。不清楚您的程序真正想要完成什么,但这几乎肯定不是您想要做的

FIFOs:您似乎知道使用FIFOs在线程之间进行通信是一种可疑的设计,但如果您被告知要使用它们,那么您必须正确使用它们

(1) 打开FIFO时(不指定非阻塞模式)
open
将被阻塞,直到FIFO的每一端都有读写器。这意味着所有3个线程将阻塞各自的FIFO open调用,直到信号处理程序(请参阅下面的问题)运行并打开FIFO进行写入

(二)即使您通过了OPEN,也只有一个线程将读取并使用信号处理程序写入的字符串。其他线程将坐在阻塞位置尝试读取空的FIFO,并且永远不会处理任何内容。当前,您只需在读取FIFO的线程中调用
exit
,这将结束程序,但不是你到底想干什么

(3) 不需要在每个线程中打开FIFO。您可以在创建线程之前打开FIFO,并将FIFO文件描述符传递给每个线程,或者将其设置为全局

(4) 每次通过
while(1)
循环打开(而不是关闭)每个线程中的FIFO。这样一来,文件描述符很快就会用完

信号处理程序:您不应该在信号处理程序中使用非异步安全调用。您至少有3个fopen、fput、fclose。理想情况下,您希望在信号处理程序中执行非常简单的操作,比如只设置一个全局开关,然后退出。因此,如果这不仅仅是一个大脑死亡的类分配,您应该重新考虑这一点

我建议你详细说明你的计划目标,你可以得到一些关于如何实现目标的建议