2014-11-22 71 views
0

我需要使用SIGUSR1和SIGUSR2並從管道讀取一些文本。一個線程必須讀取奇數符號,而另一個線程必須讀取偶數符號。主線程打開.txt文件並將信息寫入管道,2個線程從管道讀取符號並寫入其.txt文件。 我試圖使用sigwait,但它看起來不能正常工作。有任何想法嗎? 非常感謝你)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

Whay究竟發生了什麼?看起來它不能正常工作是不夠的信息 – user2717954 2014-11-22 16:16:14

+0

你的代碼有一件事是錯誤的:它沒有任何錯誤處理。零。 – 2014-11-22 16:20:04

+0

我給了他信貸,他從問題中刪除錯誤處理代碼,使其更易於讀取 – user2717954 2014-11-22 16:25:42

回答

0

sigwait等很好地工作。

但是,這裏有兩個「經典」問題:第一,假設同步行爲不成立,第二,緩衝。

異步進程:

首先,例如,在我的系統,給定的5個字節的輸入文件,父進程寫入所有字節(包括一個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會先接受它的信號。事實上,在上述情況中,首先接受信號和read()的是child2。 (這裏的另一個複雜的因素是傳統的UNIX信號不排隊所以,child1將只接受一個SIGUSR1,不知道以前的任何冗餘信號。)

緩衝:

我推斷你的第二個問題在於,您看不到孩子的輸出,也不會看到終端和輸出文件。這只是a mismatch between your expectations and those output streams' default buffering。改變緩衝區,或者直接刷新它們,你會看到每個子節點至少寫入一個字節。

+0

如何處理信號的行爲? – JeSa 2014-11-22 17:11:55

+0

@JeSa,你可以讓父母發出第一個孩子的信號_once_,然後讓孩子們彼此發出信號。 – pilcrow 2014-11-22 19:06:07