我编写了非常简单的程序,使用信号量:我创建信号量,多次分叉进程;在每个子进程中,我生成一种唯一的字符串,打开文件,而不是在无限循环中等待信号量,逐个字符写入输出文件"唯一字符串"字符并为另一个进程释放信号量。
但。。。它不知何故无法正常工作。我想知道为什么以及如何修复它。
这是我的代码:
/* test.c */
// gcc test.c -o test -lpthread
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <semaphore.h>
#include <time.h>
#include <fcntl.h>
#define SEMAPHORE_NAME "write_sync_sem"
void child_process_routine(sem_t **semaphore);
int main(int argc, char const *argv[])
{
/*
Create semaphore
*/
sem_t *semaphore = sem_open(SEMAPHORE_NAME, O_CREAT, 0644, 1);
if (semaphore == SEM_FAILED)
{
perror("Failed to create semaphore");
exit(EXIT_FAILURE);
}
int i = 0;
for (i = 0; i < 5; ++i)
{
pid_t pid = fork();
switch (pid)
{
case -1:
perror("Failed to fork process.n");
exit(EXIT_FAILURE);
break;
case 0:
child_process_routine(&semaphore);
break;
default:
printf("i = %dn", i);
break;
}
}
getchar();
sem_close(semaphore);
return 0;
}
void child_process_routine(sem_t **semaphore)
{
time_t tm;
srand((unsigned)time(&tm) + getpid());
int unique_number = rand();
char unique_str[50] = {0};
sprintf(unique_str, "such string wow very unique %d-%dn", (int)tm, unique_number);
int fd = open("output", O_RDWR | O_CREAT, 0666);
if (fd == -1)
{
perror("Failed to open output file");
exit(EXIT_FAILURE);
}
while (1)
{
if (sem_wait(*semaphore) == -1)
{
perror("Error waiting for semaphore");
exit(EXIT_FAILURE);
}
char *pCh = unique_str;
while (*pCh != ' ')
{
if (write(fd, pCh, sizeof(char)) == -1)
{
perror("Error writing to output file");
exit(EXIT_FAILURE);
}
pCh++;
}
if (sem_post(*semaphore) == -1)
{
perror("Error releasing semaphore");
exit(EXIT_FAILURE);
}
}
close(fd);
}
预期产出:
such string wow very unique 1425893996-318951960
such string wow very unique 1425893996-318951960
such string wow very unique 1425893996-926144838
such string wow very unique 1425893996-926144838
such string wow very unique 1425893996-1232743880
...
但是得到:
such string wow very unique 1425893996-926144838
such string wow very unique 1425893996-926144838
such string wow very unique 1425893996-926144838
such string wow very unique 1425893996-926144838
such string wow very unique 14258939such string wow very unique 1425893996-1232743880
such string wow very unique 1425893996-1232743880
such string wow very unique 1425893996-1232743880
such string wow very unique 1425893996-123274388such string wow very unique 1425893996-624961104
such string wow very unique 1425893996-624961104
such string wow very unique 1425such string wow very unique 1425893996-18011055
such string wow very unique 1425893996-18011055
such string wow very unique 1425893996-18011055
such string wow very unique 1425893996-18011055
such string wow very unique 1425893996-18011055
写入是缓冲的。尝试在打开调用中使用O_SYNC或在写入 while 循环后调用 fsync(),以确保在释放信号量之前将数据刷新到磁盘。
the local file structure[fd] is probably not updated
across the children, as they each open'd the file separately.
Suggest
always opening file with 'FILE * fp = fopen( "output", "r" );
then in the child, after getting the semaphore,
calling 'fseek( fp, 0, SEEK_END );'
then going into the loop to write to the file
after the loop ends, call 'fflush( fp );'
then releasing the semaphore
Although the parent process can eventually exit
(or abruptly exit via 'exit()')
The children never exit,
so when the parent exits, the children become zombies.
Note: zombie processes are difficult to get rid of
short of rebooting the computer
Note: in main(), after closing the semaphore
a call to sem_unlink() needs to be performed
otherwise the semaphore continues to exist