目标是让输出从1开始,到150,此时只有1到60,有多个重复。我想让main保持不变,只使用信号量处理process((函数。这是我对如何使用post和wait的解释。如果这是错误的,请告诉我。
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
// //dev/shm/sem.X <- unlinks
sem_t *sem;
/*
sem = sem_open("X",O_CREAT | O_EXCL, 0777, N);
sem_unlink("X");
sem_getvalue(sem,&N);
sem_post(sem);
*/
void process(){
int ret;
int N = 1;
int a;
sem = sem_open("X",O_CREAT | O_EXCL, 0777, 1);
sem_unlink("X");
for(int i = 0; i< 50; i++){
sem_wait(sem);
FILE* infile = fopen ("infile.txt", "r");
fscanf (infile, "%d", &N);
fclose (infile);
N++;
printf("N: %d Process ID: %d n",N,getpid());
infile = fopen("infile.txt", "w");
fprintf(infile,"%d",N);
fclose(infile);
sem_post(sem);
}
exit(0);
}
int main(){
FILE *fp = fopen("infile.txt","w");
fprintf(fp,"%d", 1);
fclose(fp);
int pid, pid1, pid2;
pid = fork();
if(pid == 0){
//child1, Last
printf("Starting Process C: n");
process();
}
else{
pid1 = fork();
if(pid1 == 0){
//child2, Middle
printf("Starting Process B: n");
process();
}
else{
pid2 = fork();
if(pid2 == 0){
//child 3, First
printf("Starting Process A: n");
process();
}
else{
}
}
}
//sem_close(&X);
}
在process
中执行sem_open
,然后执行sem_unlink
是不正确的。
每个进程将获得一个不同的信号量,因此它们将而不是坐标。
将sem_open
移动到main
,然后移除sem_unlink
。然后,所有进程都将使用相同/正确的信号量。
请注意,主/主进程不执行wait
[并立即终止],因此子进程附加到init进程。更好的做法:main
底部的while (wait(NULL) >= 0);
我们需要在main
的底部做sem_close
,然后做sem_unlink
下面是一些重构的代码。注释:
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
// //dev/shm/sem.X <- unlinks
sem_t *sem;
#if 0
sem = sem_open("X", O_CREAT | O_EXCL, 0777, N);
sem_unlink("X");
sem_getvalue(sem, &N);
sem_post(sem);
#endif
void
process()
{
int ret;
int N = 1;
int a;
// NOTE/BUG: by doing this here each process gets it's own semaphore so nothing
// will be coordinated
#if 0
sem = sem_open("X", O_CREAT | O_EXCL, 0777, 1);
sem_unlink("X");
#endif
for (int i = 0; i < 50; i++) {
sem_wait(sem);
FILE *infile = fopen("infile.txt", "r");
fscanf(infile, "%d", &N);
fclose(infile);
N++;
printf("N: %d Process ID: %d n", N, getpid());
infile = fopen("infile.txt", "w");
fprintf(infile, "%d", N);
fclose(infile);
sem_post(sem);
}
exit(0);
}
int
main()
{
FILE *fp = fopen("infile.txt", "w");
fprintf(fp, "%d", 1);
fclose(fp);
// NOTE/FIX: one semaphore for all processes
#if 1
sem = sem_open("X", O_CREAT | O_EXCL, 0777, 1);
//sem_unlink("X");
#endif
int pid, pid1, pid2;
pid = fork();
if (pid == 0) {
// child1, Last
printf("Starting Process C: n");
process();
}
else {
pid1 = fork();
if (pid1 == 0) {
// child2, Middle
printf("Starting Process B: n");
process();
}
else {
pid2 = fork();
if (pid2 == 0) {
// child 3, First
printf("Starting Process A: n");
process();
}
else {
}
}
}
// sem_close(&X);
// NOTE/FIX: wait for all subprocesses to finish
#if 1
while (1) {
pid = wait(NULL);
if (pid < 0)
break;
}
#endif
// NOTE/FIX: we must close and unlink so that we can be invoked again
#if 1
sem_close(sem);
sem_unlink("X");
#endif
return 0;
}
上面的方法有效,但我会使用循环来启动这三个进程,而不是嵌套的if/else
语句。如果我们必须创建1000个流程,这个解决方案将更加明显:
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
// //dev/shm/sem.X <- unlinks
sem_t *sem;
#if 0
sem = sem_open("X", O_CREAT | O_EXCL, 0777, N);
sem_unlink("X");
sem_getvalue(sem, &N);
sem_post(sem);
#endif
void
process()
{
int ret;
int N = 1;
int a;
// NOTE/BUG: by doing this here each process gets it's own semaphore so nothing
// will be coordinated
#if 0
sem = sem_open("X", O_CREAT | O_EXCL, 0777, 1);
sem_unlink("X");
#endif
for (int i = 0; i < 50; i++) {
sem_wait(sem);
FILE *infile = fopen("infile.txt", "r");
fscanf(infile, "%d", &N);
fclose(infile);
N++;
printf("N: %d Process ID: %d n", N, getpid());
infile = fopen("infile.txt", "w");
fprintf(infile, "%d", N);
fclose(infile);
sem_post(sem);
}
exit(0);
}
int
main()
{
FILE *fp = fopen("infile.txt", "w");
fprintf(fp, "%d", 1);
fclose(fp);
// NOTE/FIX: one semaphore for all processes
#if 1
sem = sem_open("X", O_CREAT | O_EXCL, 0777, 1);
//sem_unlink("X");
#endif
pid_t pid;
for (int count = 1; count <= 3; ++count) {
pid = fork();
if (pid == 0)
process();
}
// NOTE/FIX: wait for all subprocesses to finish
#if 1
while (1) {
pid = wait(NULL);
if (pid < 0)
break;
}
#endif
// NOTE/FIX: we must close and unlink so that we can be invoked again
#if 1
sem_close(sem);
sem_unlink("X");
#endif
return 0;
}