1

I'm trying to create a program in C for Unix. Given an array I should pass every item of the array from parent process to its child through shared memory and using a semaphore. This is what I've got.

const key_t sem_key = (key_t)0x12345611; const key_t shm_key = (key_t)0x12339611; int sem_wait(int semafor_id) { struct sembuf sb; sb.sem_num = 0; sb.sem_op = -1; sb.sem_flg = SEM_UNDO; return semop(semafor_id, &sb, 1); } int sem_signal(int semafor_id) { struct sembuf sb; sb.sem_num = 0; sb.sem_op = 1; sb.sem_flg = SEM_UNDO; return semop(semafor_id, &sb, 1); } int main(int argc, char *argv[]) { int status; char str[3]; str[0] = 'z'; str[1] = 'x'; str[2] = 'y'; // Create shared memory int memory_id = shmget(shm_key, 1, 0600 | IPC_CREAT | IPC_EXCL); if (memory_id < 0) { printf("Shared memory creating failed\n"); return 1; } // Create semafor int semafor_id = semget(sem_key, 10, 0600 | IPC_CREAT | IPC_EXCL); if (semafor_id < 0) { printf("SEMAFOR creating failed\n"); return 1; } semctl(semafor_id, 0, SETVAL, 1); // init semafor pid_t pid = fork(); if (pid < 0) printf("FORK FAILED\n"); else if (pid > 0) { printf("PARENT\n"); void *address = shmat(memory_id, NULL, 0); if (address == NULL) { printf("Failed to attach memory\n"); return 1; } if (sem_wait(semafor_id) < 0) // sem_wait() decrements (locks) the semaphore pointed to by sem. { printf("Failed wait parent\n"); return 1; } for (int i = 0; i < 3; i++) { void *address = shmat(memory_id, NULL, 0); if (address == NULL) { printf("Failed to attach memory\n"); return 1; } printf("writer started.\n"); char *data = (char *) address; *data = str[i]; printf("writer ended.\n"); } if (shmdt(address) != 0) printf("Failed to detach shared memory\n"); if (sem_signal(semafor_id) < 0) printf("Failed signal parent\n"); else printf("Parent leave generating number\n"); // wait for child wait(&status); printf("Destroy semafor\n"); semctl(semafor_id, 0, IPC_RMID, 0); printf("Destroy shared memory\n"); shmctl(memory_id, IPC_RMID, 0); return 0; } // close parent case else { printf("CHILD\n"); if (sem_wait(semafor_id) < 0) printf("FAILED wait child\n"); else { void *address = shmat(memory_id, NULL, 0); if (address == NULL) { printf("Failed to atach memory in child\n"); return 1; } char *data = (char *) address; printf("Child read data %c\n", *data); if (shmdt(address) != 0) printf("Failed to detach shared memory in child\n"); } } if (sem_signal(semafor_id) < 0) printf("Failed signal child\n"); else printf("Leave data reading\n"); return 0; } 

The current output is this:

writer started writer ended writer started writer ended writer started writer ended child read data y destroy semafor destroy shared memory 

As you can see the parent write in the shared memory 3 times and then the child get the access of the shared memory printing the data of the shared memory. The output I'd like to have is this:

writer started writer ended child read data z writer started writer ended child read data x writer started writer ended child read data y destroy semafor destroy shared memory 
2
  • screen shots are unnecessary, you can just copy/paste as you have done with your desired output. Just label it as "current output". Good luck. Commented Dec 24, 2015 at 20:57
  • There are multiple problems with this code. Is this a home task? What exactly is unclear to you? Commented Dec 24, 2015 at 22:03

1 Answer 1

2

The problem is in the logic. After removing boilerplate code, the logic is as follows:

Get shared memory Get semaphore with value 1 fork in parent: wait semaphore (problem #1, #2) <-- supposed to decrement it to 0 for(i=0;i<3;++i) { write next char <<-- no synchronization here :-( } signal semaphore wait for child STOP in child: wait semaphore (problem #1) read next char signal semaphore (problem #3) STOP 

in english:

the writer acquires write lock writes 3 values into the same location then signals the reader to read data. At this moment writer moves on to wait for child PID to die. The reader reads the last value once signals the semaphore then exits. At this moment writer sees reader died cleans up ...and exits 

Problem #1: parent and child processes run concurrently at the same time. Any of them can first succeed at sem_wait. If child does that first it would print out gibberish initial uninitialized value from shared memory and parent would be locked waiting for semaphore forever. Try adding imaginary (or not) sleep(1) into parent before wait semaphore. This will emulate processor context switch.

Problem #2: You wait/signal only once. E.g. you write all the values and only then signal. That is why only the last value is printed.

Problem #3: Child does not have any loops. How is he supposed to read 3 values?!

The logic should be:

Writer Do 3 times: acquire write semaphore write next value signal reader semaphore wait child to die clean up exit reader: Do 3 times: acquire reader semaphore read next value signal writer semaphore exit 
Sign up to request clarification or add additional context in comments.

2 Comments

how many semaphore do I need? 1 or 2 (reader semaphore and writer semaphore) ?
Yes, because of Issue #1 you need a write semaphore and a read semaphore.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.