Reputation: 572
I have written this code which is supposed to make N producers (P) and a consumer (C). Those two exchange K messages which are in two separate shared memory segments (sms). P's send to C a line and their pid. C sends back this line capitalized with the pid of the P that sent it. When K messages have been sent C must calculate and print how many times P's have read their own message capitalized. I put a wait(NULL) in the end so that C waits for all P's to put their personal pid_match in a buffer of a 3rd sms so it can read the right values after. Instead when i execute the code it only reads the pid_match from the 1st P and then terminates. Why does that happen. I post the code below. If any examples of execution are usefull i can provide them.
#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,"\0"); 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] != '\0')
{
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;
}
Upvotes: 1
Views: 342
Reputation: 409356
The wait
function with a NULL
argument only waits for one child process to exit. Then it stops waiting.
You need to wait for all processes to exit.
You can do that by saving all child-process pids, and then wait in a loop until they have all exited (checking using the return value of wait
).
Upvotes: 3