我必须在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.
再次 - 在发送信号后,我必须发送一条消息进行处理。所以,它有点工作。但非常非常糟糕。
答案 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
所做的更改只会影响该进程,而不会影响其他进程。