带有 wait(NULL) 的 C 程序没有像它应该的那样结束
C programm with wait(NULL) doesnt end like it should
我写了这段代码,它应该有 N 个生产者 (P) 和一个消费者 (C)。这两个交换 K 消息,它们位于两个单独的共享内存段 (sms) 中。 P 向 C 发送一行和他们的 pid。 C 发回此行,并用发送它的 P 的 pid 大写。当发送了 K 条消息后,C 必须计算并打印出 P 读取了自己的大写消息的次数。我在最后放了一个 wait(NULL) 以便 C 等待所有 P 将他们的个人 pid_match 放入第三条短信的缓冲区中,以便它可以在之后读取正确的值。相反,当我执行代码时,它只从第一个 P 读取 pid_match 然后终止。为什么会这样。我post下面的代码。如果有什么执行的例子有用我可以提供。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "myheader.h"
int main (int argc , char* argv[]){
if(argc<3) {
printf("Programm needs more arguments (K and N) \n");
return(-1);
}
else
{
const int SHMSIZE = sizeof(struct message); // Shared Memory size = the size of a message
int K, N, k, n, child_pid, shmid_in, shmid_out, shmid_pid, full_in, empty_in, full_out, empty_out, empty_pid, full_pid, pid_match=0,status,G;
key_t shmkey_in, shmkey_out, semkey0_in, semkey1_in, semkey0_out, semkey1_out;
struct message *shm_in, *shm_out;
int *shm_pid;
//struct sembuf oparray[1]={0,1,0};
K=atoi(argv[1]);
N=atoi(argv[2]);
const int shm_pidsize = N*sizeof(int);
if(K==0 || N==0) return 0; //if no producers exist the programm should exit
printf("%d %d \n", K, N );
/* --- Keys Initialization --- */
shmkey_in = ftok("/OS1.c", 1);
shmkey_out = ftok("/OS1.c", 2);
semkey0_in = ftok("/OS1.c", 3); // full_in semkey
semkey1_in = ftok("/OS1.c", 4); // empty_in semkey Tou P oi 2 gia to sms in (apo P se C dld)
semkey0_out = ftok("/OS1.c", 5); // full_out semkey
semkey1_out = ftok("OS1.c", 6); // empty_out semkey Tou P oi 2 gia to sms out (apo C se P dld)
/* --- Shared memory creation --- */
shmid_in = shmget(IPC_PRIVATE,SHMSIZE, IPC_CREAT | 0666);
shmid_out = shmget(IPC_PRIVATE,SHMSIZE, IPC_CREAT | 0666);
shmid_pid = shmget(IPC_PRIVATE,shm_pidsize,IPC_CREAT | 0666); // shm_pid creation
shm_in = (struct message*)shmat(shmid_in,NULL,0);
shm_out = (struct message*)shmat(shmid_out,NULL,0);
shm_pid = (int*)shmat(shmid_pid,NULL,0); // shm_pid attach
/* --- Semaphore creation --- */
full_in = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
empty_in = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
full_out = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
empty_out = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
full_pid = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
empty_pid = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
/* --- Semaphore Initialization --- */
union semum init0,init1;
init0.val=0;
init1.val=1;
semctl(full_in,0,SETVAL,init0); // full_in = 0
semctl(empty_in,0,SETVAL,init1); // empty_in = 1
semctl(full_out,0,SETVAL,init0); // full_out = 0
semctl(empty_out,0,SETVAL,init1); // emty_out = 1
semctl(full_pid,0,SETVAL,init0); // pid_full = 0
semctl(empty_pid,0,SETVAL,init1); // pid_empty = 1
/* --- Semaphore oparations buffers --- */
struct sembuf full_in_up = {0,1,0};
struct sembuf full_in_down = {0,-1,0};
struct sembuf empty_in_up = {0,1,0}; // Operations of P to semaphores 0,1,2
struct sembuf empty_in_down = {0,-1,0};
struct sembuf full_out_up = {0,1,0};
struct sembuf full_out_down = {0,-1,0};
struct sembuf empty_out_up = {0,1,0}; // Operations of C to semaphores 0,1,2
struct sembuf empty_out_down = {0,-1,0};
struct sembuf full_pid_up = {0,1,0};
struct sembuf full_pid_down = {0,-1,0};
struct sembuf empty_pid_up = {0,1,0};
struct sembuf empty_pid_down = {0,-1,0};
for(n=0; n<N; n++)
{
child_pid = fork();
//printf("child_pid = fork();\n ");
if (child_pid == 0)
{
printf(" --- this is %d th child with pid: %d---\n \n", n, getpid());
int pid_match = 0; // Initialize pid_match
while(1){
//printf("int pid_match = 0; // Initialize pid_match\n while(1){\n");
// printf("%d \n",semctl(empty_in,0,GETVAL));
// sleep(1);
semop(empty_in, &empty_in_down,1); // down(empty_in)
// printf("%d \n",semctl(empty_in,0,GETVAL));
//printf(" down(empty_in)\n");
struct message msg;
msg.pid = getpid();
char buf[max_line_length];
FILE *ptr_file;
ptr_file =fopen("input.txt","r");
if (!ptr_file) perror("File failed to open");
long curtime = time(NULL);
srand((unsigned int) curtime);
sleep(1); // produce & send
int i=1, j=0, luckyline = rand() % 5 + 1;
//printf("%d\n", luckyline);
while (fgets(buf, 1000, ptr_file)!=NULL && i<5)
{
if (i == luckyline)
{
//printf("%s \n",buf);
strcpy(msg.line,buf); // complete the message
strcpy(shm_in->line,msg.line); // send message to sms
shm_in->pid = getpid();
//printf("pid = %d\n",shm_in->pid );
break;
}
i++;
}
fclose(ptr_file);
// strcpy(shm_in->line, "message");
// printf("message copy\n");
// shm_in->pid = child_pid;
semop(full_in,&full_in_up,1); // up full
//printf("shared memory in full \n");
// read from C and kill if K messages have been sent
semop(full_out,&full_out_down,1); // down full
//if (strcmp(shm_out->line,"kill")!=0) printf("%s\n", shm_out->line);
if (strcmp(shm_out->line,"kill") == 0)
{
semop(empty_pid,&empty_pid_down,1);
shm_pid[j]=pid_match;
j++;
semop(full_pid,&full_pid_up,1);
printf("%d pid_match = %d\n",getpid(),pid_match );
printf("kill\n");
exit(1);
}
if (shm_out->pid == getpid())
{
//strcpy(shm_out->line,"[=10=]"); shm_out->pid = 0;
printf("Pid's match\n");
pid_match++;
}
semop(empty_out,&empty_out_up,1); // empty up
}
//sleep(20);
}else if(child_pid < 0){
perror("fork failed\n");
}else
{
// break;
}
}
for (k=0; k<K; k++)
{
int j=0;
struct message m_out;
//printf("Consumer running\n");
semop(full_in,&full_in_down,1); //down full _in
//sleep(1);
//printf("Full got 'downed'\n");
m_out.pid = shm_in->pid;
while (shm_in->line[j] != '[=10=]')
{
m_out.line[j] = toupper(shm_in->line[j]); // write in m_out->line the content of shm_in->line capitalized
j++;
}
/*if (k == K)
{
printf("kill\n");
strcpy(shm_out->line, "kill");
}*/
semop(empty_in,&empty_in_up,1); //up empty_in
semop(empty_out,&empty_out_down,1); // down empty_out
//printf("shm_in->line = %s \n", shm_in->line );
// m_out->line = shm_in->line; // capitalize & send
//strcpy(shm_out->line,m_out.line);
//shm_out->pid = m_out.pid;
printf("shm_in->line = %s \n", shm_in->line );
strcpy(shm_out->line,m_out.line);
printf("shm_out->line = %s\n", shm_out->line);
shm_out->pid = m_out.pid;
semop(full_out,&full_out_up,1); //up full
}
if (k == K)
{
printf("C kill\n");
semop(empty_out,&empty_out_down,1);
strcpy(shm_out->line, "kill");
semop(full_out,&full_out_up,1);
}
wait(NULL);
//sleep(2);
//printf("pid_match = %s\n",pid_match);
for(G=0; G<N; G++){
//sleep(2);
pid_match += shm_pid[G];
//printf("(pid_match = %s\n",pid_match);
if(G == N-1)
printf("Completed execution, exit %d\n",pid_match );
}
/* --- TERM ---*/
semctl(full_out,0,IPC_RMID,0);
semctl(full_in,0,IPC_RMID,0);
semctl(empty_out,IPC_RMID,0);
semctl(empty_in,0,IPC_RMID,0);
semctl(full_pid,0,IPC_RMID,0);
semctl(empty_pid,0,IPC_RMID,0);
shmdt(shm_pid);
shmdt(shm_in);
shmdt(shm_out);
}
return 0;
}
我写了这段代码,它应该有 N 个生产者 (P) 和一个消费者 (C)。这两个交换 K 消息,它们位于两个单独的共享内存段 (sms) 中。 P 向 C 发送一行和他们的 pid。 C 发回此行,并用发送它的 P 的 pid 大写。当发送了 K 条消息后,C 必须计算并打印出 P 读取了自己的大写消息的次数。我在最后放了一个 wait(NULL) 以便 C 等待所有 P 将他们的个人 pid_match 放入第三条短信的缓冲区中,以便它可以在之后读取正确的值。相反,当我执行代码时,它只从第一个 P 读取 pid_match 然后终止。为什么会这样。我post下面的代码。如果有什么执行的例子有用我可以提供。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "myheader.h"
int main (int argc , char* argv[]){
if(argc<3) {
printf("Programm needs more arguments (K and N) \n");
return(-1);
}
else
{
const int SHMSIZE = sizeof(struct message); // Shared Memory size = the size of a message
int K, N, k, n, child_pid, shmid_in, shmid_out, shmid_pid, full_in, empty_in, full_out, empty_out, empty_pid, full_pid, pid_match=0,status,G;
key_t shmkey_in, shmkey_out, semkey0_in, semkey1_in, semkey0_out, semkey1_out;
struct message *shm_in, *shm_out;
int *shm_pid;
//struct sembuf oparray[1]={0,1,0};
K=atoi(argv[1]);
N=atoi(argv[2]);
const int shm_pidsize = N*sizeof(int);
if(K==0 || N==0) return 0; //if no producers exist the programm should exit
printf("%d %d \n", K, N );
/* --- Keys Initialization --- */
shmkey_in = ftok("/OS1.c", 1);
shmkey_out = ftok("/OS1.c", 2);
semkey0_in = ftok("/OS1.c", 3); // full_in semkey
semkey1_in = ftok("/OS1.c", 4); // empty_in semkey Tou P oi 2 gia to sms in (apo P se C dld)
semkey0_out = ftok("/OS1.c", 5); // full_out semkey
semkey1_out = ftok("OS1.c", 6); // empty_out semkey Tou P oi 2 gia to sms out (apo C se P dld)
/* --- Shared memory creation --- */
shmid_in = shmget(IPC_PRIVATE,SHMSIZE, IPC_CREAT | 0666);
shmid_out = shmget(IPC_PRIVATE,SHMSIZE, IPC_CREAT | 0666);
shmid_pid = shmget(IPC_PRIVATE,shm_pidsize,IPC_CREAT | 0666); // shm_pid creation
shm_in = (struct message*)shmat(shmid_in,NULL,0);
shm_out = (struct message*)shmat(shmid_out,NULL,0);
shm_pid = (int*)shmat(shmid_pid,NULL,0); // shm_pid attach
/* --- Semaphore creation --- */
full_in = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
empty_in = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
full_out = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
empty_out = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
full_pid = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
empty_pid = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
/* --- Semaphore Initialization --- */
union semum init0,init1;
init0.val=0;
init1.val=1;
semctl(full_in,0,SETVAL,init0); // full_in = 0
semctl(empty_in,0,SETVAL,init1); // empty_in = 1
semctl(full_out,0,SETVAL,init0); // full_out = 0
semctl(empty_out,0,SETVAL,init1); // emty_out = 1
semctl(full_pid,0,SETVAL,init0); // pid_full = 0
semctl(empty_pid,0,SETVAL,init1); // pid_empty = 1
/* --- Semaphore oparations buffers --- */
struct sembuf full_in_up = {0,1,0};
struct sembuf full_in_down = {0,-1,0};
struct sembuf empty_in_up = {0,1,0}; // Operations of P to semaphores 0,1,2
struct sembuf empty_in_down = {0,-1,0};
struct sembuf full_out_up = {0,1,0};
struct sembuf full_out_down = {0,-1,0};
struct sembuf empty_out_up = {0,1,0}; // Operations of C to semaphores 0,1,2
struct sembuf empty_out_down = {0,-1,0};
struct sembuf full_pid_up = {0,1,0};
struct sembuf full_pid_down = {0,-1,0};
struct sembuf empty_pid_up = {0,1,0};
struct sembuf empty_pid_down = {0,-1,0};
for(n=0; n<N; n++)
{
child_pid = fork();
//printf("child_pid = fork();\n ");
if (child_pid == 0)
{
printf(" --- this is %d th child with pid: %d---\n \n", n, getpid());
int pid_match = 0; // Initialize pid_match
while(1){
//printf("int pid_match = 0; // Initialize pid_match\n while(1){\n");
// printf("%d \n",semctl(empty_in,0,GETVAL));
// sleep(1);
semop(empty_in, &empty_in_down,1); // down(empty_in)
// printf("%d \n",semctl(empty_in,0,GETVAL));
//printf(" down(empty_in)\n");
struct message msg;
msg.pid = getpid();
char buf[max_line_length];
FILE *ptr_file;
ptr_file =fopen("input.txt","r");
if (!ptr_file) perror("File failed to open");
long curtime = time(NULL);
srand((unsigned int) curtime);
sleep(1); // produce & send
int i=1, j=0, luckyline = rand() % 5 + 1;
//printf("%d\n", luckyline);
while (fgets(buf, 1000, ptr_file)!=NULL && i<5)
{
if (i == luckyline)
{
//printf("%s \n",buf);
strcpy(msg.line,buf); // complete the message
strcpy(shm_in->line,msg.line); // send message to sms
shm_in->pid = getpid();
//printf("pid = %d\n",shm_in->pid );
break;
}
i++;
}
fclose(ptr_file);
// strcpy(shm_in->line, "message");
// printf("message copy\n");
// shm_in->pid = child_pid;
semop(full_in,&full_in_up,1); // up full
//printf("shared memory in full \n");
// read from C and kill if K messages have been sent
semop(full_out,&full_out_down,1); // down full
//if (strcmp(shm_out->line,"kill")!=0) printf("%s\n", shm_out->line);
if (strcmp(shm_out->line,"kill") == 0)
{
semop(empty_pid,&empty_pid_down,1);
shm_pid[j]=pid_match;
j++;
semop(full_pid,&full_pid_up,1);
printf("%d pid_match = %d\n",getpid(),pid_match );
printf("kill\n");
exit(1);
}
if (shm_out->pid == getpid())
{
//strcpy(shm_out->line,"[=10=]"); shm_out->pid = 0;
printf("Pid's match\n");
pid_match++;
}
semop(empty_out,&empty_out_up,1); // empty up
}
//sleep(20);
}else if(child_pid < 0){
perror("fork failed\n");
}else
{
// break;
}
}
for (k=0; k<K; k++)
{
int j=0;
struct message m_out;
//printf("Consumer running\n");
semop(full_in,&full_in_down,1); //down full _in
//sleep(1);
//printf("Full got 'downed'\n");
m_out.pid = shm_in->pid;
while (shm_in->line[j] != '[=10=]')
{
m_out.line[j] = toupper(shm_in->line[j]); // write in m_out->line the content of shm_in->line capitalized
j++;
}
/*if (k == K)
{
printf("kill\n");
strcpy(shm_out->line, "kill");
}*/
semop(empty_in,&empty_in_up,1); //up empty_in
semop(empty_out,&empty_out_down,1); // down empty_out
//printf("shm_in->line = %s \n", shm_in->line );
// m_out->line = shm_in->line; // capitalize & send
//strcpy(shm_out->line,m_out.line);
//shm_out->pid = m_out.pid;
printf("shm_in->line = %s \n", shm_in->line );
strcpy(shm_out->line,m_out.line);
printf("shm_out->line = %s\n", shm_out->line);
shm_out->pid = m_out.pid;
semop(full_out,&full_out_up,1); //up full
}
if (k == K)
{
printf("C kill\n");
semop(empty_out,&empty_out_down,1);
strcpy(shm_out->line, "kill");
semop(full_out,&full_out_up,1);
}
wait(NULL);
//sleep(2);
//printf("pid_match = %s\n",pid_match);
for(G=0; G<N; G++){
//sleep(2);
pid_match += shm_pid[G];
//printf("(pid_match = %s\n",pid_match);
if(G == N-1)
printf("Completed execution, exit %d\n",pid_match );
}
/* --- TERM ---*/
semctl(full_out,0,IPC_RMID,0);
semctl(full_in,0,IPC_RMID,0);
semctl(empty_out,IPC_RMID,0);
semctl(empty_in,0,IPC_RMID,0);
semctl(full_pid,0,IPC_RMID,0);
semctl(empty_pid,0,IPC_RMID,0);
shmdt(shm_pid);
shmdt(shm_in);
shmdt(shm_out);
}
return 0;
}