2014-11-22 73 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