Use semaphores to synchronize shared memory - c

I have the following code which works fine with the sleep time. But I want to remove sleep and use semaphores to synchronize the threads ( so that the reader waits till data is available in shmptr.) How do I do that? What do I use:
sem_t mutex or
pthread_mutex_t mutex?
P.S : I tried using both above options separately (not shown in above code though) but didn't get desired result.Most of the times I was getting error in shmget in reader - "shmget in reader: No such file or directory".
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <semaphore.h>
#include <errno.h>
void *write(void *t)
{ char str[100] = "\0";
char str1[50];
key_t key;
char *shmptr;
int shmid;
if( (key = ftok("shmSemphore.c",'B')) == -1)
{
perror("ftok in writer");
pthread_exit(NULL);
}
if( (shmid = shmget(key, 1024, 0666 | IPC_CREAT)) == -1)
{
perror("shmget in writer");
pthread_exit(NULL);
}
shmptr = shmat(shmid,0,0);
if( (shmptr == (char *)(-1)))
{
perror("shmget in writer");
pthread_exit(NULL);
}
printf("ENter your text :- ");
//scanf("%s",str);
fgets(str,sizeof(str),stdin);
strcpy(shmptr,str);
sleep(2);
shmdt(shmptr);
if( shmctl(shmid, IPC_RMID, NULL) == -1 )
{
perror("shmctl");
exit(-1);
}
pthread_exit(NULL);
}
void *read(void *t)
{ sleep(2);
key_t key;
char *shmptr;
int shmid;
if( (key = ftok("shmSemphore.c",'B')) == -1)
{
perror("ftok in writer");
pthread_exit(NULL);
}
if( (shmid = shmget(key, 1024, 0)) == -1)
{
perror("shmget in reader");
pthread_exit(NULL);
}
shmptr = shmat(shmid,0,0);
if( (shmptr == (char *)-1))
{
perror("shmget in writer");
pthread_exit(NULL);
}
printf("your text:- %s \n",shmptr);
pthread_exit(NULL);
}
int main()
{
pthread_t reader,writer;
int rt;
long t = 0;
rt = pthread_create(&writer,NULL,write,(void *)t);
/*if(rt == -1)
{ perror("writer thread");
pthread_exit(NULL);
}*/
rt = pthread_create(&reader,NULL,read,(void *)t);
/*if(rt == -1)
{ perror("writer thread");
pthread_exit(NULL);
}*/
pthread_join(writer,NULL);
pthread_join(reader,NULL);
return 0;
}

Related

Scanf printing weird characters after the input

This code takes in input N-file names and generates N-threads, then the main thread writes something and puts it in a buffer for each thread, and each threads writes their buffer content on their own file. Everything works fine but on the file, the input is like this and i don't know why, hope someone can help me, thanks in advance
Hello����������������������������������������������������������������������������������������������������������������������������
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define fflush(stdin) while (getchar() != '\n')
int n_threads;
FILE **source_files;
char **files;
char buffers[128][128];
pthread_mutex_t *ready;
pthread_mutex_t *done;
char buff[256];
void *thread_function(void *);
int main(int argc, char **argv) {
long i, j, ret;
pthread_t tid;
if (argc < 2) {
printf("Error: Usage -> prog | file1 ... fileN\n");
exit(1);
}
n_threads = argc - 1;
files = argv + 1;
for(i = 0; i < n_threads; i++) {
for(j = 0; j < n_threads; j++) {
if(strcmp(files[i], files[j]) == 0 && i != j) {
puts("Strings are equal.\n");
exit(1);
}
}
}
puts("Strings are different");
/*buffers = (char **)malloc(sizeof(char *) * n_threads);
if(buffers == NULL) {
printf("Malloc error.\n");
exit(1);
}*/
source_files = (FILE **)malloc(sizeof(FILE *) * n_threads);
if(source_files == NULL) {
printf("Malloc error.\n");
exit(1);
}
ready = malloc(sizeof(pthread_mutex_t));
done = malloc(sizeof(pthread_mutex_t));
if (ready == NULL || done == NULL) {
printf("Malloc error.\n");
exit(1);
}
if(pthread_mutex_init(ready, NULL) || pthread_mutex_init(done, NULL) || pthread_mutex_lock(ready)) {
printf("Mutex init error.\n");
exit(1);
}
for(i = 0; i < n_threads; i++) {
if(pthread_create(&tid, NULL, thread_function, (void *) i)) {
printf("Error while creating thread %ld.\n", i);
exit(1);
}
}
//signal(SIG_INT, printer);
i = 0;
while(1) {
if(pthread_mutex_lock(done)) {
printf("Mutex lock error.\n");
exit(1);
}
ret = scanf(" %s", buff);
if(ret == EOF) {
printf("Scanf error.\n");
exit(1);
}
if (ret == 0) {
printf("Non compliant input.\n");
exit(1);
}
getchar();
puts("before strcpy\n");
strcpy(buffers[i],buff);
puts("after strcpy\n");
if(pthread_mutex_unlock(ready)) {
printf("Mutex unlock error.\n");
exit(1);
}
i=(i+1)%n_threads;
}
}
void *thread_function (void *arg) {
int fd;
//FILE *file;
long me = (long) arg;
printf("Thread %ld started.\n", me);
puts("before opening file.\n");
fd = open(files[me], O_CREAT | O_RDWR | O_TRUNC, 0666);
//file = fdopen(fd, "w+");
puts("after opening file.\n");
while(1) {
if(pthread_mutex_lock(ready)) {
printf("Mutex lock error.\n");
exit(1);
}
printf("Thread %ld took string %s.\n", me, buffers[me]);
puts("before fprintf.\n");
//fprintf(file, "%s", buffers[me]);
write(fd, buffers[me], 128);
puts("after fprintf.\n");
if(pthread_mutex_unlock(done)) {
printf("Mutex unlock error.\n");
exit(1);
}
}
}

Building semaphores using Mutexes

I'm reading Modern Operating Systems and there's a exercise that asks you to build a counting-semaphore with a binary-semaphore.
I was wondering if I could do it with semaphores & shared memory (C and POSIX IPC).
I'll leave a simplification of my program here.
typedef struct sem {
int semid; /* contains two semaphores with value set to 1, one for the critical region and the other for locking */
int shmid; /* shared counter */
}Sem;
/* the parent process spawns a few child processes and then waits for them */
void child() {
Sem *s;
s = get_sem();
down_sem(s);
printf("working...");
sleep(5);
printf("finished!");
up_sem(s);
}
void down_sem(Sem *s) {
int n;
enter_critical(s); // down to critical region sem
n = get_counter(s);
if (n == 0) {
exit_critical(s); // up to critical region sem
acquire_lock(s); // down to lock sem
} else {
n--;
exit_critical(s); // up to critical region sem
}
}
void up_sem(Sem *s) {
int n;
enter_critical(s);
n = get_counter(s);
n++;
if (n == 1) {
exit_critical(s);
release_lock(s); // up to lock sem
} else {
exit_critical(s);
}
}
But this doesn't work since some processes block in the lock semaphore forever. I'm just now learning these concepts so my design is probably totally off.
I can share the complete code if you wish.
Thanks in advance!
EDIT: requested mre
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <sys/shm.h>
#define NPROC 5
#define SLOTS 2
#define PATH "."
#define SID 'S'
#define SEMN 2
#define SHMID 'M'
#define SHM_SIZE 32
#define CRIT 0
#define LOCK 1
#define UP 1
#define DOWN -1
typedef struct sem {
int shmid;
int semid;
}Sem;
typedef union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
}Args;
void err (char *msg) {
char error[50];
int n;
n = snprintf(error, 50, "[%d] %s", getpid(), msg);
error[n] = 0;
perror(error);
exit(1);
}
int* get_n(Sem *s) {
int *data = NULL;
data = shmat(s->shmid, (void *)0, 0);
if (data == (int *)(-1))
err("get_n shmat");
return data;
}
void dettach_n(int *data) {
if (shmdt(data) == -1)
err("dettach_n shmdt");
}
void enter_crit(Sem *s) {
struct sembuf sb;
sb.sem_num = CRIT;
sb.sem_op = DOWN;
printf("[%d] enter crit\n", getpid());
if (semop(s->semid, &sb, 1) == -1)
err("enter crit");
}
void exit_crit(Sem *s) {
struct sembuf sb;
sb.sem_num = CRIT;
sb.sem_op = UP;
printf("[%d] exit crit\n", getpid());
if (semop(s->semid, &sb, 1) == -1)
err("exit crit");
}
void acquire_lock(Sem *s) {
struct sembuf sb;
sb.sem_num = LOCK;
sb.sem_op = DOWN;
printf("[%d] acquire lock\n", getpid());
if (semop(s->semid, &sb, 1) == -1)
err("acquire lock");
}
void release_lock(Sem *s) {
struct sembuf sb;
sb.sem_num = LOCK;
sb.sem_op = UP;
printf("[%d] release lock\n", getpid());
if (semop(s->semid, &sb, 1) == -1)
err("release lock");
}
int sem_init(Sem *s, int n) {
key_t key;
Args arg;
int *data;
/* sem */
if ((key = ftok(PATH, SID)) == -1) {
return -1;
}
if ((s->semid = semget(key, SEMN, 0600 | IPC_CREAT)) == -1) {
return -1;
}
arg.val = 1;
if (semctl(s->semid, 0, SETVAL, arg) == -1) {
return -1;
}
if (semctl(s->semid, 1, SETVAL, arg) == -1) {
return -1;
}
/* mem */
if ((key = ftok(PATH, SHMID)) == -1) {
return -1;
}
if ((s->shmid = shmget(key, SHM_SIZE, 0664 | IPC_CREAT)) == -1) {
return -1;
}
data = shmat(s->shmid, (void *)0, 0);
if (data == (int *)(-1)) {
return -1;
}
*data = n;
if (shmdt(data) == -1) {
return -1;
}
return 0;
}
int sem_get(Sem *s) {
key_t key;
if ((key = ftok(PATH, SID)) == -1) {
return -1;
}
if ((s->semid = semget(key, SEMN, 0)) == -1) {
return -1;
}
if ((key = ftok(PATH, SHMID)) == -1) {
return -1;
}
if ((s->shmid = shmget(key, SHM_SIZE, 0)) == -1) {
return -1;
}
return 0;
}
int sem_up(Sem *s) {
int *data;
enter_crit(s);
data = get_n(s);
printf("[%d] read %d\n", getpid(), *data);
(*data)++;
if (*data == 1) {
printf("[%d] now is %d\n", getpid(), *data);
dettach_n(data);
exit_crit(s);
release_lock(s);
} else {
exit_crit(s);
}
return 0;
}
int sem_down(Sem *s) {
int *data;
enter_crit(s);
data = get_n(s);
printf("[%d] checked %d\n", getpid(), *data);
if (*data == 0) {
dettach_n(data);
exit_crit(s);
acquire_lock(s);
} else {
(*data)--;
dettach_n(data);
exit_crit(s);
}
return 0;
}
int sem_rm(Sem *s) {
if (semctl(s->semid, 0, IPC_RMID) == -1)
return -1;
if (shmctl(s->shmid, 0, IPC_RMID) == -1)
return -1;
return 0;
}
void child() {
pid_t pid;
Sem s;
pid = getpid();
printf("\x1b[31m[%d] hello!\033[0m\n", pid);
if (sem_get(&s) == -1) {
perror("sem_get");
exit(1);
}
sem_down(&s);
printf("\x1b[32m[%d] working...\033[0m\n", pid);
sleep(5);
printf("\x1b[32m[%d] finishing...\033[0m\n", pid);
sem_up(&s);
printf("\x1b[34m[%d] **child leaving**\033[0m\n", pid);
exit(0);
}
int main() {
Sem s;
int i;
if (sem_init(&s, SLOTS) == -1) {
perror("sem_init");
exit(1);
}
printf("[%d] parent\n", getpid());
for (i = 0; i < NPROC; i++) {
switch(fork()) {
case 0:
child();
case -1:
perror("fork");
exit(1);
}
}
printf("waiting for children...\n");
for (i = 0; i < NPROC; i++)
wait(NULL);
if (sem_rm(&s) == -1) {
perror("sem_rm");
exit(1);
}
printf("good bye!\n");
return 0;
}
The problem was in the up_sem function. It only does an up to the lock sem (release_lock func) if n was previously 0. This is incorrect since it might be several process waiting.
My solution was adding an extra shared memory counting the waiting processes and doing an up to the lock sem when that number is greater than 0.

Working with semaphores and shared memory in C

The program should create 200000 integers and write 2000 to a shared memory. A forked process should read 2000 from shared memory and the parent should write the next 2000 to shared memory.
if i use the code below without sleep, the parent first creates all 200000 integers and then the child reads the same integers from shared memory.
With sleep everything looks good, but we have to use semaphore.
shm.c (parent):
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <sys/wait.h>
#define N_DATA 200000
#define N_SHARED 2000
#define LOCK -1
#define UNLOCK 1
static struct sembuf semaphore;
char shmidArg[32];
char semidArg[32];
int *shmData;
int i, j;
int status;
char *strsignal(int sig);
pid_t pid;
static int shmid;
static int semid;
char *strsignal(int sig);
/** Semaphore Operation */
static int semaphore_operation (int op) {
semaphore.sem_num = 1;
semaphore.sem_op = op;
semaphore.sem_flg = IPC_NOWAIT;
if( semop (semid, &semaphore, 1) == -1) {
perror(" semop ");
exit (EXIT_FAILURE);
}
return 1;
}
int main(int argc, char **argv) {
/* Ein Shared-Memory-Segment einrichten */
shmid = shmget(IPC_PRIVATE, N_SHARED*sizeof(int), IPC_CREAT | SHM_R | SHM_W);
if (shmid == -1) {
perror("shmid");
exit(1);
}
printf("Shared-Memory-ID: %d\n",shmid);
/* Pointer zu Shared-Memory-Segment erhalten */
shmData = (int *)shmat(shmid,0, 0);
if (shmData == (int *)(-1)) {
perror("shmat");
exit(1);
}
/* Semaphore anlegen */
semid = semget(IPC_PRIVATE, 1, IPC_CREAT | SHM_R | SHM_W);
if (semid < 0) {
perror("semid");
exit(1);
}
printf ("Semaphor-ID : %d\n", semid);
/* Semaphor mit 1 initialisieren */
if (semctl (semid, 0, SETVAL, (int) 1) == -1) {
perror("semctl");
}
snprintf(shmidArg,32, "%d", shmid);
snprintf(semidArg,32, "%d", semid);
/** erstellen des Kindprozesses */
pid = fork();
// Kindprozess
if (pid == 0) {
execlp("./shm_child",shmidArg,semidArg,NULL);
} else if (pid < 0) {
perror("Kindprozess konnte nicht erzeugt werden!");
return 1;
}
// Elternprozess
else {
/** ininitalisieren des Zufallsgenerator durch aktuellen Zeitstempel */
srand48(time(NULL));
for(i=0;i<N_DATA;i=i+N_SHARED) {
semaphore_operation(LOCK);
for (j=0; j<N_SHARED; j++) {
shmData[j] = lrand48();
//MSZ
//printf("SHM-->%d-->%d\n",i+1,shmData[i]);
}
// if(i == 0 || i == 2000) {
printf("Parent-->%d-->0-->%d\n",i,shmData[0]);
printf("Parent-->%d-->1999->%d\n",i,shmData[1999]);
// }
semaphore_operation(UNLOCK);
//sleep(1);
}
}
//MSZ
//sleep(2);
printf("PID: %d\n", pid);
if (waitpid(pid, &status, 0) == -1) {
perror("wait konnte nicht erzeugt werden!");
return 1;
}
if (WIFEXITED(status)) {
printf("Exitcode: %d\n", WEXITSTATUS(status));
semctl (semid, 0, IPC_RMID, 0);
shmctl (shmid, IPC_RMID, NULL);
//If process terminaded by a signal
} else if (WIFSIGNALED(status)) {
printf("Signal: %d %s\n", WTERMSIG(status), strsignal(WTERMSIG(status)));
semctl (semid, 0, IPC_RMID, 0);
shmctl (shmid, IPC_RMID, NULL);
}
}
shm_child.c (Child):
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#define N_DATA 6000
#define N_SHARED 2000
#define LOCK -1
#define UNLOCK 1
int i,j;
int *shmData;
static int shmid;
static int semid;
static struct sembuf semaphore;
/** Semaphore Operation */
static int semaphore_operation (int op) {
semaphore.sem_num = 0;
semaphore.sem_op = op;
semaphore.sem_flg = SEM_UNDO;
if( semop (semid, &semaphore, 1) == -1) {
perror(" semop ");
exit (EXIT_FAILURE);
}
return 1;
}
int main(int argc, char **argv) {
shmid = atoi(argv[0]);
semid = atoi(argv[1]);
printf("\nshm_child shared memoryid:%d\n",shmid);
printf("shm_child Semaphoren-ID:%d\n",semid);
/* Pointer auf Shared-Memory erstellen */
shmData = (int *)shmat(shmid,0,0);
if (shmData == (int *)(-1)) {
perror("shmat");
exit(1);
}
for(i=0;i<N_DATA;i=i+N_SHARED) {
semaphore_operation(LOCK);
for(j=0;j<N_SHARED;j++) {
//printf("%d-->%d --> %d\n",i,j+1,shmData[j]);
}
// if(i == 0 || i == 2000) {
printf("child-->%d-->0-->%d\n",i,shmData[0]);
printf("child-->%d-->1999->%d\n",i,shmData[1999]);
// }
semaphore_operation(UNLOCK);
sleep(1);
}
return 0;
}
Please help us
Thank you guys
Edit: Thank you very much for your answers. I can't mark the right answer because i dont know what its right. But i dont want try anything more. 15 hours are enough
The writer process shall give reader a permission to read, and wait for the reading completion. After that the reader shall give writer a permission to proceed, and wait for writing completion.
This goal cannot be achieved with a single semaphore. You need two, along the lines of:
// parent aka writer
writer_barrier = semaphore(UNLOCKED);
reader_barrier = semaphore(LOCKED);
start_reader();
while(...) {
lock(writer_barrier);
write_data();
unlock(reader_barrier);
}
// child aka reader
while(....)
lock(reader_barrier);
read_data();
unlock(writer_barrier);
}

Initialise semaphores using sem_open

In my producer and consumer problem, I use sem_open() to initialize the semaphores. How could I test if sem_open() works in a correct way?
The program can be compiled, but when I run the program it does not print anything. I test the program and found the problem maybe about sem_open(). I find if I comment the sem_open() in the program, the program will run correctly.
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#include <unistd.h>
#define BUFFER_SIZE 10
int buffer[BUFFER_SIZE];
pthread_t pro_thread, con_thread;
pthread_mutex_t mutex;
int counter = 0;
sem_t *empty, *full;
void print_buffer(int counter) {
for (int i = 0; i < counter; i ++)
{
printf("*");
}
printf("\n");
}
void* producer(void* var) {
int item;
while(1) {
item = rand() % 100 + 1;
sem_wait(empty);
pthread_mutex_lock(&mutex);
while (counter == BUFFER_SIZE)
; // waiting
if(counter < BUFFER_SIZE) {
buffer[counter] = item;
counter ++;
printf("Producer: ");
print_buffer(counter);
}
sleep(1);
pthread_mutex_unlock(&mutex);
sem_post(full);
}
}
void* consumer(void* var) {
int item;
while(1) {
sem_wait(full);
pthread_mutex_lock(&mutex);
while (counter == 0)
; // waiting
if(counter > 0) {
counter --;
print_buffer(counter);
}
sleep(1);
pthread_mutex_unlock(&mutex);
sem_post(empty);
}
}
int main(int argc, char *argv[]) {
pthread_mutex_init(&mutex, NULL);
empty = sem_open("/mysem", O_CREAT, 0644, BUFFER_SIZE);
full = sem_open("/mysem", O_CREAT, 0644, 0);
pthread_create(&pro_thread, NULL, producer, NULL);
pthread_create(&con_thread, NULL, consumer, NULL);
pthread_exit(NULL);
return 0;
}
As stated in the sem_open man page:
The semaphore is identified by name.
Since your code provides the same name value (/mysem) for both sem_open calls it results in referencing the same semaphore for both full and empty. That's clearly not what the logic of the program should be. Instead, open different semaphores for each. It's also best practice to check the return values of all function calls.
empty = sem_open("/empty_sem", O_CREAT, 0644, BUFFER_SIZE);
if (empty == SEM_FAILED) {
perror("Failed to open semphore for empty");
exit(-1);
}
full = sem_open("/full_sem", O_CREAT, 0644, 0);
if (full == SEM_FAILED) {
sem_close(empty);
perror("Failed to open semphore for full");
exit(-1);
}

Confusion with forked process?

I am trying to do first child function, for example, printing out a string : hello!, and go back to parent process. Then, I forked anothrer n processes for the second child function, which will count the shared memory number. I suppose there only shows one "all done" in the end, but it shows two? thanks for your help!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/wait.h>
#include <fcntl.h>
#define NUM_LINES 5
char * shm;
void child_func(char *shm)
{
while (atoi(shm) != NUM_LINES)
{
// P(sem);
printf("now reading word:%d\n", atoi(shm) );
*shm+=1;
// V(sem);
}
exit(0);
}
void parent_func(pid_t pid)
{
int status;
pid_t pid_wait;
do
{
pid_wait = waitpid(pid, &status, WNOHANG);
}while (pid_wait != pid);
// printf("Process %d done\n", getppid());
}
int main(int argc, char const *argv[])
{
/* declarations */
pid_t pid[8];
int ret, shmid, status,corpse, i, ave, n;
char fn[20];
key_t key = 123;
char *string_back;
/* create share memory */
if ((shmid = shmget(key, SHMSIZE, IPC_CREAT|666)) <0)
{
perror("shmget");
exit(1);
}
/* attach shm */
if ((shm = shmat(shmid, NULL, 0)) == (char*)-1)
{
perror("shmat");
exit(1);
}
/* init shm value */
*shm = '0';
/* input */
printf("please enter n:\n");
scanf("%d", &n);
/* section 1 */
pid[0] = fork();
if (pid[0] == 0) // child processes
{
printf("hello !\n");
}
else if (pid[0] >0)
{
parent_func(pid[0]);
}
/* section 2 */
for (i=0;i<n;i++)
{
pid[i] = fork();
if (pid[i] == 0) // child processes
{
child_func(shm);
}
else if (pid[i] >0)
{
parent_func(pid[i]);
}
}
printf("all done\n");
/* detach shm */
shmdt(shm);
/* destroy shm */
int retval = shmctl(shmid, IPC_RMID, NULL);
if (retval < 0) perror("remove shm");
return 0;
}
After adding exit(0) in first section, I only get one "all done" in the last, which is the answer I want.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/wait.h>
#include <fcntl.h>
#define NUM_LINES 5
char * shm;
void child_func(char *shm)
{
while (atoi(shm) != NUM_LINES)
{
// P(sem);
printf("now reading word:%d\n", atoi(shm) );
*shm+=1;
// V(sem);
}
exit(0);
}
void parent_func(pid_t pid)
{
int status;
pid_t pid_wait;
do
{
pid_wait = waitpid(pid, &status, WNOHANG);
}while (pid_wait != pid);
// printf("Process %d done\n", getppid());
}
int main(int argc, char const *argv[])
{
/* declarations */
pid_t pid[8];
int ret, shmid, status,corpse, i, ave, n;
char fn[20];
key_t key = 123;
char *string_back;
/* create share memory */
if ((shmid = shmget(key, SHMSIZE, IPC_CREAT|666)) <0)
{
perror("shmget");
exit(1);
}
/* attach shm */
if ((shm = shmat(shmid, NULL, 0)) == (char*)-1)
{
perror("shmat");
exit(1);
}
/* init shm value */
*shm = '0';
/* input */
printf("please enter n:\n");
scanf("%d", &n);
/* section 1 */
pid[0] = fork();
if (pid[0] == 0) // child processes
{
printf("hello !\n");
/* problem solved here */
exit(0);
}
else if (pid[0] >0)
{
parent_func(pid[0]);
}
/* section 2 */
for (i=0;i<n;i++)
{
pid[i] = fork();
if (pid[i] == 0) // child processes
{
child_func(shm);
}
else if (pid[i] >0)
{
parent_func(pid[i]);
}
}
printf("all done\n");
/* detach shm */
shmdt(shm);
/* destroy shm */
int retval = shmctl(shmid, IPC_RMID, NULL);
if (retval < 0) perror("remove shm");
return 0;
}

Resources