2014-11-22 2 views
0

Мне нужно использовать SIGUSR1 и SIGUSR2 и прочитать текст из трубы. Один поток должен читать нечетные символы, а другой должен читать четные символы. Основной поток открывает файл .txt и записывает информацию в канал, а 2 потока считывают символы из канала и записывают в их .txt-файлы. Я попытался использовать сигвайт, но похоже, что он работает неправильно. Есть идеи? Большое спасибо)Сигналы Linux C

#include <sys/types.h> 
#include <unistd.h> 
#include <iostream> 
#include <printf.h> 
#include <stdio.h> 
#include <sys/wait.h> 
#include <stdlib.h> 
#include <cerrno> 
#include <signal.h> 
#include <fcntl.h> 
using namespace std; 
static bool a=false; 
static int c; 

main(int argc, char** argv) 
{ 
    int fildes[2]; 
    char ch,ch1,ch2; 
    FILE *fp,*f1,*f2; 
    int stat,sig; 

    sigset_t set1; 
    sigset_t set2; 
    sigemptyset(&set1); 
    sigemptyset(&set2); 
    sigaddset(&set1,SIGUSR1); 
    sigaddset(&set2,SIGUSR2); 
    sigprocmask(SIG_BLOCK,&set1,NULL); 
    sigprocmask(SIG_BLOCK,&set2,NULL); 

    pid_t p1,p2; 
    pipe(fildes); 
    cout<<argv[1]<< " " <<argv[2]<< " " <<argv[3]<<endl; 
    fp=fopen(argv[1],"r"); 
    f1=fopen(argv[2],"a"); 
    f2=fopen(argv[3],"a"); 
    int chet=2; 
    p1=fork(); 
    if (!p1) 
    { 
     do 
     {  
      sigwait(&set1,&sig); 
      read(fildes[0], &ch1, 1); 
      printf("%c",ch1); 
      fprintf(f1,"%c",ch1); 

     } 
     while(!a); 
     exit(0); 
    } 
    p2=fork(); 
    if (!p2) 
    { 
      do 
      {  
       sigwait(&set2,&sig); 
       read(fildes[0], &ch2, 1); 
       printf("%c",ch2); 
       fprintf(f2,"%c",ch2); 

      } 
      while(!a); 
      exit(0); 
    } 
    else 
    { 
     while(!feof(fp)) 
     { 
       ch=fgetc(fp); 
       write(fildes[1],&ch,1); 
       if(chet%2==0) 
        kill(p1,SIGUSR1); 
       else kill(p2,SIGUSR2); 
       chet++; 
       //sleep(1/10); 
     } 
     a=true; 

     wait(&stat); 
     close(fildes[0]); 
     close(fildes[1]); 
     fclose(f1); 
     fclose(f2); 
     fclose(fp); 
    } 
} 
+1

Что происходит? Похоже, что он не работает правильно, недостаточно информации. – user2717954

+0

В коде есть что-то не так: в нем нет обработки ошибок. Нуль. –

+0

Я дал ему кредит, что он удалил код обработки ошибок из вопроса, чтобы сделать его более читаемым – user2717954

ответ

0

sigwait и так далее работать отлично.

Однако у вас есть две «классические» проблемы: во-первых, предположение о синхронном поведении, которое не выполняется, и, во-вторых, буферизация.

Несинхронизированные процессы:

Во-первых, к примеру, на моей системе, учитывая входной файл в пять байт, родительский процесс записывает все байты (включая EOF маркер - упс!) И посылает все сигналы перед тем либо дочерний процесс даже называет sigwait:

[parent] read(5, "BaRd\n", 4096)  = 5 
[parent] write(4, "B", 1)   = 1 
[parent] kill(5404, SIGUSR1)   = 0 
[parent] write(4, "a", 1)   = 1 
[parent] kill(5405, SIGUSR2)   = 0 
[parent] write(4, "R", 1)   = 1 
[parent] kill(5404, SIGUSR1)   = 0 
[parent] write(4, "d", 1)   = 1 
[parent] kill(5405, SIGUSR2)   = 0 
[parent] write(4, "\n", 1)   = 1 
[parent] kill(5404, SIGUSR1)   = 0 
[parent] read(5, "", 4096)   = 0 
[parent] write(4, "\377", 1)   = 1      # Oops! we wrote stdio's EOF marker 
[parent] kill(5405, SIGUSR2)   = 0 
[parent] wait4(-1, <unfinished ...> 
[child2] rt_sigtimedwait([USR2], NULL, NULL, 8) = 12   # Oops! child2 is going first 
[child2] read(3, "B", 1)    = 1 
[child2] rt_sigtimedwait([USR2], NULL, NULL, 8 <unfinished ...> # Oops! ordinary UNIX signals don't queue 
[child1] rt_sigtimedwait([USR1], NULL, NULL, 8) = 10 
[child1] read(3, "a", 1)    = 1 
[child1] rt_sigtimedwait([USR1], NULL, NULL, 8 

дети не гарантированно будет готов, как только вы звоните fork(). Более того, это не гарантирует, что child1 примет его сигнал первым. Действительно, в приведенном выше примере child2 принимает сигнал и read() s первый. (Другим осложняющим фактором здесь является то, что обычные сигналы UNIX не в очереди Таким образом, child1 будет принимать только один SIGUSR1, не знают о каких-либо предыдущих избыточных сигналов.).

Буферизация:

Я выводя, что ваш второй проблема заключается в том, что вы не видите выходных данных от детей, ни к терминалу, ни к их выходным файлам. Это просто a mismatch between your expectations and those output streams' default buffering. Измените буферизацию или явно очистите их, и вы увидите, что каждый дочерний элемент записывает по меньшей мере один байт.

+0

что я могу делать с поведением сигналов? – JeSa

+0

@JeSa, у вас может быть родительский сигнал первого дочернего _once_, а потом дети передают друг другу сигналы. – pilcrow

Смежные вопросы