使用C

时间:2015-06-12 22:37:32

标签: c linux multiprocessing signals semaphore

我必须在Linux上用C编写程序。它必须有3个进程 - 首先从STDIN读取,通过FIFO将消息发送到第二个进程,该进程计算接收消息的长度并将结果发送到第三个进程(也通过FIFO),将其显示在STDOUT上。我必须使用信号量同步它。此外,我必须添加信号处理(我正在使用共享内存) - 一个信号到结束程序,第二个停止它,第三个恢复。信号可以发送到任何进程。我已经有了一些代码,但它没有按预期工作。

第一个问题是同步 - 正如您可以通过运行它看到的那样,第一个消息是由第二个进程接收的,但随后它被卡住了。第一个和第二个进程显示他们的消息,但不显示第三个消息。有非常相似的,所以令人困惑。我必须发送另一条消息,然后P3显示前一条消息的长度。

第二个问题是信号 - 发送一个后,我必须按Enter键(用于SIGUSR)或发送消息(用于SIGINT)以便它被服务。

任何想法有什么不对?我之前发布的内容有一些改进,但它仍然无法正常工作,我没有太多时间来完成它(直到星期一)。我知道这是很多代码,但如果有人能够分析第二和第三个流程的沟通,我将非常感激。

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <sys/sem.h>
#include <signal.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>

#define WRITE 1
#define READ 0
#define MEM_ID 1
#define MEM_SIZE 1

#define OK  "[ \033[1;32mOK\033[0m ]\n"
#define ERR "[\033[1;31mFAIL\033[0m] "
#define SIGNAL "\033[1;33m\033[5m>> SIGNAL <<\033[0m\n"

#define S1 SIGINT
#define S2 SIGUSR1
#define S3 SIGUSR2
#define S4 SIGCONT

/* union semun - from POSIX specification for semctl() */
/* NB: on Mac OS X, and apparently in defiance of POSIX, <sys/sem.h> declares union semun */
/*
union semun
{
    int val;
    struct semid_ds *buf;
    unsigned short  *array;
} arg;
*/

/*
union semun
{
    int val;
    ushort *array;
};
*/

int process1(void);
int process2(void);
int process3(void);
void signal_callback(int signo);
//void signal_handling(int snd, int rcv);   // JL
void signal_handling(void);     // JL
void sem_down(int semid, int semnum);
void sem_up(int semid, int semnum);

char work = 1, quit = 0;
char inter_snd = 0, inter_rcv = 0;
struct sembuf semstruct;
int sem23, sem12, mem;
char *message;
int res[3];

static const char *fifoname[] = { "1fifo2", "2fifo3" };

static
void main_quit(int n)
{
    printf("%s(): signal %d\n", __func__, n);  // JL
    kill(res[0], S1);
}

int main(void)
{
    //union semun arg;  // JL
    printf("[G] Launching\n");

    signal(SIGINT, main_quit);
    signal(SIGTERM, main_quit);
    // creating FIFO
    printf("[G] Creating FIFO... ");
    res[0] = mkfifo(fifoname[0], 0644);
    res[1] = mkfifo(fifoname[1], 0644);
    if ((res[0] == -1) || (res[1] == -1))
    {
        perror(ERR);
        unlink(fifoname[0]);
        unlink(fifoname[1]);
        return 1;
    }
    else
        printf(OK);

    // create two semaphores and set values
    printf("[G] Creating semaphores... ");
    sem12 = semget(READ, 1, IPC_CREAT | 0644);
    sem23 = semget(WRITE, 1, IPC_CREAT | 0644);

    if ((sem23 == -1) || (sem12 == -1))
    {
        perror(ERR);
        return 1;
    }
    else
        printf(OK);

    printf("[G] Initializing semaphores values... ");
    semctl(sem12, 0, SETVAL, 0);
    semctl(sem12, 1, SETVAL, 1);
    semctl(sem23, 0, SETVAL, 0);
    semctl(sem23, 1, SETVAL, 1);
    printf(OK);

    // creating shared memory
    printf("[G] Reserving shared memory... ");
    mem = shmget(MEM_ID, MEM_SIZE, IPC_CREAT | 0644);
    message = (char *)shmat(mem, 0, 0);

    if (mem == -1)
    {
        perror(ERR);
        return 1;
    }
    else
        printf(OK);

    if ((res[0] = fork()) == 0)
    {
        process1();
        exit(0);
    }

    if ((res[1] = fork()) == 0)
    {
        process2();
        exit(0);
    }

    if ((res[2] = fork()) == 0)
    {
        process3();
        exit(0);
    }

    printf("[G] Building process tree... ");
    if ((res[0] == -1) || (res[1] == -1) || (res[2] == -1))
    {
        perror(ERR);
        return 1;
    }
    else
    {
        printf(OK);
        printf("[G] P1[pid]: %d, P2[pid]: %d, P3[pid]: %d\n", res[0], res[1], res[2]);
    }

    wait(NULL);
    wait(NULL);
    wait(NULL);

    printf("[G] Deleting FIFO... ");
    res[0] = unlink(fifoname[0]);
    res[1] = unlink(fifoname[1]);
    if ((res[0] == -1) || (res[1] == -1))
        perror(ERR);
    else
        printf(OK);

    printf("[G] Freeing shared memory... ");
    res[0] = shmdt((char *)message);
    res[1] = shmctl(mem, IPC_RMID, 0);
    if ((res[0] == -1) || (res[1] == -1))
        perror(ERR);
    else
        printf(OK);

    printf("[G] Deleting semaphores... ");
    res[0] = semctl(sem23, 0, IPC_RMID, 0);
    res[1] = semctl(sem12, 0, IPC_RMID, 0);
    if ((res[0] == -1) || (res[1] == -1))
        perror(ERR);
    else
        printf(OK);

    printf("[G] Ending...\n");
    return 0;
}

int process1(void)
{
    char tab[100];
    FILE *fifoh;

    signal(S1, signal_callback);
    signal(S2, signal_callback);
    signal(S3, signal_callback);
    signal(S4, signal_callback);

    fifoh = fopen(fifoname[0], "w");
    setbuf(fifoh, NULL);

    printf("[P1] Ready.\n");
    //while (fgets(tab, sizeof(tab), stdin) > 0)    // JL
    while (fgets(tab, sizeof(tab), stdin) != 0)     // JL
    {
        if (work)
        {
            sem_down(sem12, WRITE);
            printf("[P1] Sending: %s", tab);
            fprintf(fifoh, "%s\n", tab);
            sem_up(sem12, READ);
        }
        //signal_handling(inter_snd, inter_rcv);    // JL
        signal_handling();  // JL
    }
    fclose(fifoh);
    printf("[P1] Ending...\n");
    return 0;
}

int process2(void)
{
    char tab[100];
    FILE *fifo_in, *fifo_out;

    printf("[P2] Ready.\n");

    fifo_in = fopen(fifoname[0], "r");
    fifo_out = fopen(fifoname[1], "w");

    setbuf(fifo_out, NULL);
    setbuf(fifo_in, NULL);

    signal(S1, signal_callback);
    signal(S2, signal_callback);
    signal(S3, signal_callback);
    signal(S4, signal_callback);

    do
    {
        if (work)
        {
            sem_down(sem12, READ);
            fscanf(fifo_in, "%s", (char *)tab);
            sem_up(sem12, WRITE);
            printf("[P2] Received \"%s\" with length %zu.\n", tab, strlen(tab));
            sem_down(sem23, WRITE);
            fprintf(fifo_out, "%d\n", (int)strlen(tab));
            sem_up(sem23, READ);
        }
        //signal_handling(inter_snd, inter_rcv);    // JL
        signal_handling();  // JL
    } while (!quit);

    fclose(fifo_in);
    fclose(fifo_out);
    printf("[P2] Ending...\n");
    return 0;
}

int process3(void)
{
    FILE *fifo_in;
    int count;

    printf("[P3] Ready.\n");

    signal(S1, signal_callback);
    signal(S2, signal_callback);
    signal(S3, signal_callback);
    signal(S4, signal_callback);

    fifo_in = fopen(fifoname[1], "r");
    setbuf(fifo_in, NULL);

    do
    {
        if (work)
        {
            sem_down(sem23, READ);
            fscanf(fifo_in, "%d\n", (int *)&count);
            sem_up(sem23, WRITE);
            printf("[P3] Received: %d characters.\n", count);
        }
        //signal_handling(inter_snd, inter_rcv);    // JL
        signal_handling();  // JL
    } while (!quit);
    fclose(fifo_in);
    printf("[P3] Ending...\n");
    return 0;
}

//void signal_handling(int snd, int rvc)
void signal_handling(void)
{
    if (inter_snd > 0)
    {
        printf("Signal received...\n");

        semstruct.sem_op = -3;
        semop(sem23, &semstruct, 1);

        *message = inter_snd;
        inter_snd = 0;

        semstruct.sem_op = 3;
        semop(sem12, &semstruct, 1);

        printf("Sending to other processes\n");
        kill(0, S4);
    }
    if (inter_rcv)
    {
        inter_rcv = 0;

        semstruct.sem_op = -1;
        semop(sem12, &semstruct, 1);

        switch (*message)
        {
        case 1:
            printf("Quitting...\n");
            quit = 1;
            break;
        case 2:
            printf("Stopping...\n");
            work = 0;
            break;
        case 3:
            printf("Starting...\n");
            work = 1;
            break;
        default:
            printf("There's garbage in memory :/..\n");
        }
        semstruct.sem_op = 1;
        semop(sem23, &semstruct, 1);
    }
}

void signal_callback(int signo)
{
    printf(SIGNAL);
    switch (signo)
    {
    case S1:
        inter_snd = 1;
        break;
    case S2:
        inter_snd = 2;
        break;
    case S3:
        inter_snd = 3;
        break;
    case S4:
        inter_rcv = 1;
        break;
    }
}

void sem_down(int semid, int semnum)
{
    semstruct.sem_flg = 0;
    semstruct.sem_num = semnum;
    semstruct.sem_op = -1;
    do
    {
        errno = 0;
        semop(semid, &semstruct, 1);
    } while (errno == EINTR);
}

void sem_up(int semid, int semnum)
{
    semstruct.sem_flg = 0;

    semstruct.sem_num = semnum;
    semstruct.sem_op = 1;
    semop(semid, &semstruct, 1);
}

预期行为:

[P3] Ready.
[P2] Ready.
[P1] Ready.
asd
[P1] Sending: asd
[P2] Received "asd" with length 3.
[P3] Received: 3 characters.
as
[P1] Sending: as
[P2] Received "as" with length 2.
[P3] Received: 2 characters.

信号:

应收到信号并发送给其他所有进程。接下来发生的事情在singnal_handling中指定。每个进程都应显示其消息(退出/停止/等)。

实际行为:

[P3] Ready.
[P2] Ready.
[P1] Ready.
asd 
[P1] Sending: asd
[P2] Received "asd" with length 3.
dd
[P1] Sending: dd
[P2] Received "dd" with length 2.
[P3] Received: 3 characters. //first message
as
[P1] Sending: as
[P2] Received "as" with length 2.
[P3] Received: 2 characters. //second
asd
[P1] Sending: asd
[P2] Received "asd" with length 3.
[P3] Received: 2 characters. // third

有了信号,好吧......我发现在SIGINT之后我可以发送消息,按两次输入然后我得到了预期的行为(退出程序)。当我发送另一个信号时,按Enter键也可以使用:

$ kill -s SIGUSR1 2900
$ kill -s SIGUSR2 2900

给出:

asd
[P1] Sending: asd
[P2] Received "asd" with length 3.
[P3] Received: 3 characters.
Signal received...
Sending to other processes
>> SIGNAL <<
Stopping...
>> SIGNAL <<
>> SIGNAL <<
>> SIGNAL <<
Signal received...
Sending to other processes
>> SIGNAL <<
>> SIGNAL <<
>> SIGNAL <<
Starting...

[P1] Sending: 
Starting...
asd
[P1] Sending: asd
[P2] Received "asd" with length 3.
Starting...
[P3] Received: 3 characters.

再次 - 在发送信号后,我必须发送一条消息进行处理。所以,它有点工作。但非常非常糟糕。

1 个答案:

答案 0 :(得分:2)

使用GCC 5.1.0,使用我用于编译Stack Overflow代码的标准编译选项,将您的代码逐字记录到运行Mac OS X 10.10.3的Mac上,我收到编译警告(我调用了您的代码{ {1}}):

semshm.c

第一个问题是Mac OS X特有的;它似乎在$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \ > -Wold-style-definition -Werror semshm.c -o semshm semshm.c:29:7: error: redefinition of ‘union semun’ union semun { ^ In file included from semshm.c:8:0: /usr/include/sys/sem.h:176:7: note: originally defined here union semun { ^ semshm.c:48:6: error: no previous prototype for ‘main_quit’ [-Werror=missing-prototypes] void main_quit(int n) { ^ semshm.c: In function ‘main_quit’: semshm.c:48:20: error: unused parameter ‘n’ [-Werror=unused-parameter] void main_quit(int n) { ^ semshm.c: In function ‘main’: semshm.c:54:17: error: unused variable ‘arg’ [-Werror=unused-variable] union semun arg; ^ semshm.c: In function ‘process1’: semshm.c:161:43: error: ordered comparison of pointer with integer zero [-Werror=extra] while (fgets(tab, sizeof(tab), stdin) > 0) { ^ semshm.c: In function ‘process2’: semshm.c:197:20: error: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘size_t {aka long unsigned int}’ [-Werror=format=] printf("[P2] Recieved \"%s\" with length %d.\n", tab, strlen(tab)); ^ semshm.c:197:20: error: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘size_t {aka long unsigned int}’ [-Werror=format=] semshm.c: In function ‘signal_handling’: semshm.c:239:26: error: unused parameter ‘snd’ [-Werror=unused-parameter] void signal_handling(int snd, int rvc) { ^ semshm.c:239:35: error: unused parameter ‘rvc’ [-Werror=unused-parameter] void signal_handling(int snd, int rvc) { ^ cc1: all warnings being treated as errors 中定义了union semun,尽管semctl()的POSIX规范 明确地说:

  

semctl()函数提供了 cmd 指定的各种信号量控制操作。第四个参数是可选的,取决于所请求的操作。如果需要,它的类型为 union semun ,应用程序应明确声明:

<sys/sem.h>

POSIX要求的唯一借口是糟糕的历史先例,Mac OS X已经过度了。因此,union semun { int val; struct semid_ds *buf; unsigned short *array; } arg; 的双重声明不会对您不利。很奇怪,POSIX需要一个额外的成员,与你指定的相比。无论如何,我评论说要通过那个宣言。

还有其他警告,尽管其中许多都不是那么严重。未使用的变量并不好,但并没有太大的危害。 struct semun%d之间的格式不匹配,如果在我的机器上,size_t查找32位值,而%d是64位数量,则很重要。 size_t的测试应为fgets();失败时它返回NULL(或0 - 我也使用0)。

最奇怪的问题是!= 0未使用的参数。调用将全局变量signal_handling()inter_snd传递给函数,但函数忽略这些值并简单地操作全局变量。这里的主叫代码和被叫代码之间至少存在严重脱节。

为了继续生活,我将inter_rcv转换为无参数函数signal_handling()并保持其身体不变(但修复了对它的所有调用)。我补充说:

void signal_handling(void);

printf("%s(): signal %d\n", __func__, n); 无视how to avoid using printf() in a signal handler的建议。我还修理了&#39; i&#39;之前&#39; e&#39;除了&#39; c&#39; 拼写错误。还要退出&#39;有两个t&#39;停止&#39;有两个p - 英语是一种奇怪的语言。

最后,我将两个FIFO名称(main_quit()1fifo2)解压缩到一个数组中:

2fifo3

并使用static const char *fifoname[] = { "1fifo2", "2fifo3" }; fifoname[0]代替文字。重复的文件名文字是个坏主意。我还使用新名称来清理(fifoname[1])FIFO,如果在创建它们之后存在它们。

  • 尽管收集了警告,但代码还不错;很少有程序在没有经过一些编辑的情况下毫发无损地传递这组选项,以使其干净利落地通过。

编译代码后,我运行了几次。最后一次运行是:

unlink(fifoname[0]); unlink(fifoname[1]);

我输入了一个被处理的中断。我输入了绝对的胡扯,其中绝对的&#39;绝对&#39;部分显然是在一个地方收到的,但是“胡扯”和“部分从未成功。这令人费解。我为每个人输入了可用的商品&#39;而对于所有外表,它完全被忽略了。我尝试了另一个中断,显然中断了事情。我试过控制-D(EOF),显然什么也没做。我使用control-backslash( control - \ )来生成一个退出信号,这确实会阻止程序。我之前做过那件事; reruns显示了清理后的智慧,发现当我收到失败消息时已经创建了FIFO,然后重新编写代码并且工作正常。输出显示绿色OK消息,并闪烁黄色$ ./semshm [G] Launching [G] Creating FIFO... [ OK ] [G] Creating semaphores... [ OK ] [G] Initializing semaphores values... [ OK ] [G] Reserving shared memory... [ OK ] [G] Building process tree... [ OK ] [G] P1[pid]: 36030, P2[pid]: 36031, P3[pid]: 36032 [P2] Ready. [P1] Ready. [P3] Ready. ^C>> SIGNAL << main_quit(): signal 2 >> SIGNAL << >> SIGNAL << >> SIGNAL << absolute baloney [P1] Sending: absolute baloney Signal received... [P2] Received "absolute" with length 8. Signal received... commestible goods for everyone ^C>> SIGNAL << >> SIGNAL << main_quit(): signal 2 >> SIGNAL << Sending to other processes >> SIGNAL << Sending to other processes >> SIGNAL << >> SIGNAL << >> SIGNAL << Quitting... >> SIGNAL << Quitting... [P2] Ending... [P3] Received: 8 characters. Signal received... Sending to other processes >> SIGNAL << >> SIGNAL << Quitting... >> SIGNAL << [P3] Ending... ^\Quit: 3 $ 消息。

所以,你没有告诉我们如何使用该程序,或者输出预期。

您没有编译器警告&#39;断言有点乐观,但事实并非如此。

现在您需要升级问题以指定/说明您提供的输入以及该输入的预期行为,并显示您实际从中获得的意外行为。

>>> SIGNAL <<<

的一个半工作版本

这是我编译和运行的已编译的部分注释代码。要在Linux或其他更准确的POSIX兼容平台上编译它(比Mac OS X更准确),您需要取消注释其中一个semshm.c块。我通常会删除union semun(现代POSIX几乎从不要求您包含它;上一个千年的旧版本确实需要它 - 请参阅POSIX 1997,但与POSIX 2004进行比较没有)。

<sys/types.h>
     

...代码加入了问题...请参阅https://stackoverflow.com/posts/30813144/revisions的修订版3 ...

     

...我在船上用这个代码跑过了30,000个字符的限制......

#include <stdio.h>

}

的另一个主要工作版本

获取有关代码应该如何工作的额外信息,并进行大量额外的诊断打印,并观察进程2和3等待未发出信号的信号量,我想出了这个代码的变体:

semshm.c

请注意两个#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ipc.h> #include <unistd.h> #include <sys/sem.h> #include <signal.h> #include <sys/shm.h> #include <sys/wait.h> #include <string.h> #include <errno.h> #define WRITE 1 #define READ 0 #define MEM_ID 1 #define MEM_SIZE 1 #define OK "[ \033[1;32mOK\033[0m ]\n" #define ERR "[\033[1;31mFAIL\033[0m] " #define SIGNAL "\033[1;33m\033[5m>> SIGNAL <<\033[0m\n" #define S1 SIGINT #define S2 SIGUSR1 #define S3 SIGUSR2 #define S4 SIGCONT int process1(void); int process2(void); int process3(void); void signal_callback(int signo); void signal_handling(void); void sem_down(int semid, int semnum); void sem_up(int semid, int semnum); char work = 1, quit = 0; char inter_snd = 0, inter_rcv = 0; struct sembuf semstruct; int sem23, sem12, mem; char *message; int res[3]; static const char *fifoname[] = { "1fifo2", "2fifo3" }; static void main_quit(int n) { printf("%s(): signal %d\n", __func__, n); kill(res[0], S1); } int main(void) { printf("[G] Launching\n"); signal(SIGINT, main_quit); signal(SIGTERM, main_quit); // creating FIFO printf("[G] Creating FIFO... "); res[0] = mkfifo(fifoname[0], 0644); res[1] = mkfifo(fifoname[1], 0644); if ((res[0] == -1) || (res[1] == -1)) { perror(ERR); unlink(fifoname[0]); unlink(fifoname[1]); return 1; } else printf(OK); // create two semaphores and set values printf("[G] Creating semaphores... "); sem12 = semget(READ, 1, IPC_CREAT | 0644); sem23 = semget(WRITE, 1, IPC_CREAT | 0644); if ((sem23 == -1) || (sem12 == -1)) { perror(ERR); return 1; } else printf(OK); printf("[G] Initializing semaphores values... "); semctl(sem12, 0, SETVAL, 0); semctl(sem12, 1, SETVAL, 1); semctl(sem23, 0, SETVAL, 0); semctl(sem23, 1, SETVAL, 1); printf(OK); // creating shared memory printf("[G] Reserving shared memory... "); mem = shmget(MEM_ID, MEM_SIZE, IPC_CREAT | 0644); message = (char *)shmat(mem, 0, 0); if (mem == -1 || message == 0) { perror(ERR); return 1; } else printf(OK); if ((res[0] = fork()) == 0) { process1(); printf("Returned from process1() - exiting\n"); exit(0); } if ((res[1] = fork()) == 0) { process2(); printf("Returned from process2() - exiting\n"); exit(0); } if ((res[2] = fork()) == 0) { process3(); printf("Returned from process3() - exiting\n"); exit(0); } printf("[G] Building process tree... "); if ((res[0] == -1) || (res[1] == -1) || (res[2] == -1)) { perror(ERR); return 1; } else { printf(OK); printf("[G] P1[pid]: %d, P2[pid]: %d, P3[pid]: %d\n", res[0], res[1], res[2]); } int corpse; int status; while ((corpse = wait(&status)) > 0) printf("[G] PID %d exited with status 0x%.4X\n", corpse, status); printf("[G] Deleting FIFO... "); res[0] = unlink(fifoname[0]); res[1] = unlink(fifoname[1]); if ((res[0] == -1) || (res[1] == -1)) perror(ERR); else printf(OK); printf("[G] Freeing shared memory... "); res[0] = shmdt((char *)message); res[1] = shmctl(mem, IPC_RMID, 0); if ((res[0] == -1) || (res[1] == -1)) perror(ERR); else printf(OK); printf("[G] Deleting semaphores... "); res[0] = semctl(sem23, 0, IPC_RMID, 0); res[1] = semctl(sem12, 0, IPC_RMID, 0); if ((res[0] == -1) || (res[1] == -1)) perror(ERR); else printf(OK); printf("[G] Ending...\n"); return 0; } int process1(void) { char tab[100]; FILE *fifoh; signal(S1, signal_callback); signal(S2, signal_callback); signal(S3, signal_callback); signal(S4, signal_callback); fifoh = fopen(fifoname[0], "w"); setbuf(fifoh, NULL); printf("[P1] Ready.\n"); while (fgets(tab, sizeof(tab), stdin) != 0) { if (work) { sem_down(sem12, WRITE); printf("[P1] Sending: %s", tab); fprintf(fifoh, "%s", tab); sem_up(sem12, READ); } else printf("[P1] Ignoring line because work is zero: %s", tab); signal_handling(); } fclose(fifoh); printf("[P1] Ending...\n"); sem_up(sem12, READ); // Crucial return 0; } int process2(void) { char tab[100]; FILE *fifo_in, *fifo_out; printf("[P2] Ready.\n"); fifo_in = fopen(fifoname[0], "r"); fifo_out = fopen(fifoname[1], "w"); setbuf(fifo_out, NULL); setbuf(fifo_in, NULL); signal(S1, signal_callback); signal(S2, signal_callback); signal(S3, signal_callback); signal(S4, signal_callback); do { if (work) { printf("[P2]: Waiting on semaphore sem12/R\n"); sem_down(sem12, READ); printf("[P2]: Proceed on semaphore sem12/R\n"); if (fscanf(fifo_in, "%s", (char *)tab) != 1) { printf("[P2]: EOF\n"); break; } printf("[P2]: Signalling semaphore sem12/W\n"); sem_up(sem12, WRITE); printf("[P2]: Proceeding semaphore sem12/W\n"); printf("[P2] Received \"%s\" with length %zu.\n", tab, strlen(tab)); printf("[P2]: Waiting on semaphore sem23/R\n"); sem_down(sem23, WRITE); printf("[P2]: Proceed on semaphore sem23/R\n"); fprintf(fifo_out, "%zu\n", strlen(tab)); printf("[P2]: Signalling semaphore sem23/W\n"); sem_up(sem23, READ); printf("[P2]: Proceeding semaphore sem23/W\n"); } else printf("[P2] Looping: work is zero\n"); printf("[P2]: signal handling\n"); signal_handling(); printf("[P2]: signal handling done\n"); } while (!quit); fclose(fifo_in); fclose(fifo_out); printf("[P2] Ending...\n"); sem_up(sem23, READ); // Crucial return 0; } int process3(void) { FILE *fifo_in; int count; printf("[P3] Ready.\n"); signal(S1, signal_callback); signal(S2, signal_callback); signal(S3, signal_callback); signal(S4, signal_callback); fifo_in = fopen(fifoname[1], "r"); setbuf(fifo_in, NULL); do { if (work) { printf("[P3]: Waiting on semaphore sem23\n"); sem_down(sem23, READ); if (fscanf(fifo_in, "%d", &count) == 1) printf("[P3] Received: %d as the length.\n", count); else { printf("[P3] Failed to read an integer\n"); break; } sem_up(sem23, WRITE); } else printf("[P3] Looping: work is zero\n"); printf("[P3]: signal handling\n"); signal_handling(); printf("[P3]: signal handling done\n"); } while (!quit); fclose(fifo_in); printf("[P3] Ending...\n"); return 0; } void signal_handling(void) { if (inter_snd > 0) { printf("PID %d: Signal received...\n", (int)getpid()); semstruct.sem_op = -3; semop(sem23, &semstruct, 1); *message = inter_snd; inter_snd = 0; semstruct.sem_op = 3; semop(sem12, &semstruct, 1); printf("Sending to other processes\n"); kill(0, S4); } else printf("PID %d: inter_snd = %d\n", (int)getpid(), inter_snd); if (inter_rcv) { inter_rcv = 0; semstruct.sem_op = -1; semop(sem12, &semstruct, 1); switch (*message) { case 1: printf("Quitting...\n"); quit = 1; break; case 2: printf("Stopping...\n"); work = 0; break; case 3: printf("Starting...\n"); work = 1; break; default: printf("There's garbage in memory :/..\n"); } semstruct.sem_op = 1; semop(sem23, &semstruct, 1); } else printf("PID %d: inter_rcv = %d\n", (int)getpid(), inter_rcv); } void signal_callback(int signo) { printf("%sSignal %d in PID %d\n", SIGNAL, signo, (int)getpid()); switch (signo) { case S1: inter_snd = 1; break; case S2: inter_snd = 2; break; case S3: inter_snd = 3; break; case S4: inter_rcv = 1; break; } } void sem_down(int semid, int semnum) { semstruct.sem_flg = 0; semstruct.sem_num = semnum; semstruct.sem_op = -1; do { errno = 0; semop(semid, &semstruct, 1); } while (errno == EINTR); } void sem_up(int semid, int semnum) { semstruct.sem_flg = 0; semstruct.sem_num = semnum; semstruct.sem_op = 1; semop(semid, &semstruct, 1); } 来电标记为“关键”&#39 ;;他们确实至关重要。另请注意,输入操作已进行错误检查;这也是至关重要的。如果你没有检查它们是否有效,你会错过EOF指示。始终,但始终检查I / O操作是否正常工作。

使用该代码,示例运行是:

sum_up()

我还没弄清楚有多少代码可以被淘汰 - 但我怀疑是这么多&#39;是一个准确的声明。信号量操作实际上没有必要;无论如何,进程将在文件流上正确阻塞。我也不相信共享内存会有所帮助。而且我并不相信$ ./semshm [G] Launching [G] Creating FIFO... [ OK ] [G] Creating semaphores... [ OK ] [G] Initializing semaphores values... [ OK ] [G] Reserving shared memory... [ OK ] [G] Building process tree... [ OK ] [G] P1[pid]: 36545, P2[pid]: 36546, P3[pid]: 36547 [P2] Ready. [P3] Ready. [P1] Ready. [P3]: Waiting on semaphore sem23 [P2]: Waiting on semaphore sem12/R absolutely-ineffable-twaddle-for-onward-transmission [P1] Sending: absolutely-ineffable-twaddle-for-onward-transmission PID 36545: inter_snd = 0 PID 36545: inter_rcv = 0 [P2]: Proceed on semaphore sem12/R [P2]: Signalling semaphore sem12/W [P2]: Proceeding semaphore sem12/W [P2] Received "absolutely-ineffable-twaddle-for-onward-transmission" with length 52. [P2]: Waiting on semaphore sem23/R [P2]: Proceed on semaphore sem23/R [P2]: Signalling semaphore sem23/W [P2]: Proceeding semaphore sem23/W [P2]: signal handling PID 36546: inter_snd = 0 PID 36546: inter_rcv = 0 [P2]: signal handling done [P2]: Waiting on semaphore sem12/R [P3] Received: 52 as the length. [P3]: signal handling PID 36547: inter_snd = 0 PID 36547: inter_rcv = 0 [P3]: signal handling done [P3]: Waiting on semaphore sem23 [P1] Ending... Returned from process1() - exiting [P2]: Proceed on semaphore sem12/R [P2]: EOF [P2] Ending... Returned from process2() - exiting [P3] Failed to read an integer [P3] Ending... Returned from process3() - exiting [G] PID 36545 exited with status 0x0000 [G] PID 36546 exited with status 0x0000 [G] PID 36547 exited with status 0x0000 [G] Deleting FIFO... [ OK ] [G] Freeing shared memory... [ OK ] [G] Deleting semaphores... [ OK ] [G] Ending... $ 非常有帮助,但可以想象在信号处理下做一些有用的事情。请注意,它不在进程之间共享(它对每个进程都是私有的),因此一个进程对work所做的更改只会影响该进程,而不会影响其他进程。