Processes with group of 2 semaphores and shared memory - c

I write a program containing two processes: the first one contains a group of two semaphores and creates the child process that reads all data in the shared memory segment and prints them.
In the second one, the child process computes the data using a compute function that returns 0 when all data are computed. It transmits them to the parent through the shared memory segment.
To write data:
On the 1st semaphore the child makes P and the parent make V.
On the 2nd semaphore the child makes V and the parent make P.
But as I'm new in this topic and still getting hardness to understand, it seems like I'm doing something wrong because it's not working as it has to be.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <semaphore.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/wait.h>
int sum =0;
int compute(int data){
sum += data;
return sum;
}
int main(){
int i;
int shm_id;
int data;
pid_t pid;
key_t shm_key;
sem_t *sem;
// unsigned int sem_value =2;
shm_key = ftok("/dev/null", 65);
shm_id = shmget(shm_id, sizeof(int), 0644 | IPC_CREAT);
if (shm_id < 0){
perror("shmgget");
exit(EXIT_FAILURE);
}
// data = shmat(shm_id, NULL, 0);
sem = sem_open("semaphore", O_CREAT | O_EXCL, 0644, 2);
for (i = 0; i < 2; i++){
pid = fork();
if (pid < 0)
{
perror("fork");
sem_unlink("semaphore");
sem_close(sem);
exit(EXIT_FAILURE);
}
else if (pid == 0)
{
break;
}
}
if (pid == 0)
{
puts("Enter the data:");
scanf("%d", &data);
//child process
sem_wait(sem);
printf("Child - %d is in critical section\n", i);
sleep(1);
puts("Enter the data:");
scanf("%d", &data);
// *shrd_value += data;
printf("Child - %d: new value of data = %d\n", i, data);
printf("Child - %d: sum of whole data by far = %d\n", i, compute(data));
sem_post(sem);
exit(EXIT_SUCCESS);
}
else if (pid > 0)
{
//parent process
while (pid = waitpid(-1, NULL, 0))
{
if (errno == ECHILD)
{
break;
}
}
puts("All children exited");
shmdt(&data);
shmctl(shm_id, IPC_RMID, 0);
sem_unlink("semaphore");
sem_close(sem);
exit(0);
}
}
Output:
Enter the data:
Enter the data:
2
Child - 0 is in critical section
1Enter the data:
Child - 1 is in critical section
Enter the data:
3
Child - 0: new value of data = 3
Child - 0: sum of whole data by far = 3
2
Child - 1: new value of data = 2
Child - 1: sum of whole data by far = 2
All children exited

I have also modified the way they write to shared memory: they write directly at the address given by shmat call that is missing in your code.
I have fixed some bugs and simplifed the code (removed the array - added detailed logging especially before and after entering the critial section):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <semaphore.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/wait.h>
int main(){
int i;
int shm_id;
pid_t pid;
int *addr;
int data;
pid_t current_pid;
key_t shm_key;
sem_t *sem;
shm_key = ftok("/dev/null", 65);
shm_id = shmget(shm_key, sizeof(int), 0644 | IPC_CREAT);
if (shm_id < 0){
perror("shmget");
exit(EXIT_FAILURE);
}
sem_unlink("semaphore");
sem = sem_open("semaphore", O_CREAT, 0644, 1);
if (sem == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
addr = (int *) shmat(shm_id, (void *) 0, 0);
if (addr == (void *) -1) {
perror("shmat");
exit(EXIT_FAILURE);
}
*addr = 0;
for (i = 0; i < 2; i++){
pid = fork();
if (pid < 0)
{
perror("fork");
sem_close(sem);
sem_unlink("semaphore");
exit(EXIT_FAILURE);
}
}
if (pid == 0)
{
current_pid = getpid();
printf("Child %d: waiting for critical section \n", current_pid);
sem_wait(sem);
printf("Child %d: enters in critical section \n", current_pid);
printf("child %d: Enter the data:\n", current_pid);
scanf("%d", &data);
printf("Child %d: new value of data = %d\n", current_pid, data);
printf("Child %d: sum of whole data so far = %d\n", current_pid, *addr += data);
sem_post(sem);
printf("Child %d exits from critical section\n", current_pid);
exit(EXIT_SUCCESS);
}
else if (pid > 0)
{
//parent process
while (pid = waitpid(-1, NULL, 0))
{
if (errno == ECHILD)
{
break;
}
}
puts("All children exited");
shmdt(addr);
shmctl(shm_id, IPC_RMID, 0);
sem_close(sem);
sem_unlink("semaphore");
exit(0);
}
exit(0);
}
Note that semaphore initial value must be 1 to have a true critical section for 2 processes.
I have also removed the sleep calls and we can see that one of the process is waiting:
Child 22514: waiting for critical section
Child 22514: enters in critical section
child 22514: Enter the data:
Child 22515: waiting for critical section
333
Child 22514: new value of data = 333
Child 22514: sum of whole data so far = 333
Child 22514 exits from critical section
Child 22515: enters in critical section
child 22515: Enter the data:
666
Child 22515: new value of data = 666
Child 22515: sum of whole data so far = 999
Child 22515 exits from critical section
All children exited
All children exited

Here's the code with producer and consumer process
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> // O_CREAT, O_EXEC
#include <errno.h> // errno, ECHILD
#include <unistd.h>
#include <sys/shm.h> // shmat(), IPC_RMID
#include <sys/wait.h>
#include <semaphore.h> // sem_open(), sem_destroy(), sem_wait()...
#include <sys/types.h> // key_t, sem_t, pid_t
#include <pthread.h>
#define BUFF 10
typedef struct data{
int buff[BUFF];
int size;
int index;
}DATA;
int main(int argc, char const *argv[])
{
sem_t *full, *empty, *access;
key_t shm_key;
int shm_id;
full = sem_open ("fullname", O_CREAT , 0644, 15);
empty = sem_open ("empty", O_CREAT , 0644, 0);
access = sem_open ("access", O_CREAT , 0644, 1);
if (argc!=2)
{
exit(1);
}
int value=atoi(argv[1]);
//initialize a shared variable in shared memory
shm_key = ftok("/dev/null", 60);
shm_id = shmget(shm_key, sizeof(DATA), 0);
// shared memory error check
if (shm_id < 0){
shm_id = shmget(shm_key, sizeof(DATA), 0644 | IPC_CREAT);
DATA *data = (DATA*) shmat (shm_id, NULL, 0);
data->size=0;
data->index=0; //index
}
printf("Shared memory id: %d\n",shm_id );
printf("Checking buffer...,\n");
//If in the buffer have free space then will wait for consumer to consume the data\n"
sem_wait(empty);
printf("\nLocking buffer to produce data\n");
sem_wait(access);
//initialize a shared variable in shared memory
shm_key = ftok("/dev/null", 60);
shm_id = shmget(shm_id, sizeof(DATA), 0644 | IPC_CREAT);
// shared memory error check
if (shm_id < 0){
perror("semaphore");
exit(EXIT_FAILURE);
}
//Shared variable
DATA *data = (DATA*) shmat (shm_id, NULL, 0);
int index=(data->size + data->index) % 15;
data->buff[index]=value;
data->size++;
printf("%d is located in %d on the buffer\n",value,index );
//consusming
// attach data to shared memory
index=data->index;
value=data->buff[index];
printf("%d now consumed\n",value );
data->size--;
data->index++;
sem_post(access);
sem_post(full);
return 0;
}

Related

How do I print stored data from the shared memory?

I have the following program:
#include <stdio.h>
#include <sys/types.h>
#define MAX_COUNT 100
void ChildProcess(void);
void ParentProcess(void);
void main(void)
{
pid_t pid;
pid = fork();
if (pid == 0)
ChildProcess();
else
ParentProcess();
}
void ChildProcess(void)
{
int i;
for (i = 1; i <= MAX_COUNT; i++)
printf(" This line is from child, value = %d\n", i);
printf(" *** Child process is done ***\n");
}
void ParentProcess(void)
{
int i;
for (i = 1; i <= MAX_COUNT; i++)
printf("This line is from parent, value = %d\n", i);
printf("*** Parent is done ***\n");
}
I have to modify it in a way that both the parent and the child print stored data from the shared memory in the following way:
Create and initialize the shared memory in the parent.
Fill the shared memory with 5 integer numbers. (I should allocate enough shared memory to store the 5 ints.)
Fork from the parent to the child.
If fork is successful, then the child process must print the values stored in the shared memory as shown in the expected output where N1, N2, N3, N4, N5 are the numbers found in the shared memory.
Expected output
What I did in the ParentProcess function is the following:
void ParentProcess(void)
{
int i;
for (i = 1; i <= MAX_COUNT; i++)
printf("This line is from parent, value = %d\n", i);
printf("*** Parent is done ***\n");
int localVar = 0;
int* p = (int*) malloc(2);
pid_t childPID = fork();
*p = 0;
if (childPID >= 0)
{
printf("\nChild process has started\n");
if (childPID == 0)
{
localVar++;
globalVar++;
printf("Child process has found the following data %d,", *p);
*p = 70;
printf( " %d,", *p);
*p = 66;
printf(" %d,", *p);
*p = 51;
printf(" %d,", *p);
*p = 90;
printf(" %d in shared memory\n",*p);
printf("Child is existing\n\n");
}
}
}
And now I realize that I did it completely wrong but I have no idea how to fix that. I suppose I have to use shmget to create the shared memory, but then what? How do I store values in it?
If you find that you cannot help me with this or it is too long, please share sources where I can learn more about C programming in Linux, particularly regarding the usage of shared memory. Thank you in advance
It may be better to make it clear what you want to do first because as far as I read your code you call fork() twice in your code (once in main() function and once in ParentProcess() function)
So I write general solution for parent/child shared memory. There are several ways to achieve shared memory but this is one example which is modified version of the code here
How to use shared memory with Linux in C
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/wait.h>
void *create_shared_memory(size_t size)
{
int protection = PROT_READ | PROT_WRITE;
int visibility = MAP_SHARED | MAP_ANONYMOUS;
return mmap(NULL, size, protection, visibility, -1, 0);
}
int main()
{
// Allocate 4 ints
void *shmem = create_shared_memory(sizeof(int)*4);
if( shmem == NULL ){
fprintf(stderr, "Failed to create shared memory\n");
return -1;
}
// Initialize 4 ints
((int*)shmem)[0] = 10;
((int*)shmem)[1] = 100;
((int*)shmem)[2] = 1000;
((int*)shmem)[3] = 10000;
int pid = fork();
if (pid == 0)
{
// Print 4 ints in child
printf("Child reading int 0: %d\n", ((int*)shmem)[0]);
printf("Child reading int 1: %d\n", ((int*)shmem)[1]);
printf("Child reading int 2: %d\n", ((int*)shmem)[2]);
printf("Child reading int 3: %d\n", ((int*)shmem)[3]);
printf("Child end\n");
}
else
{
printf("Parent waiting for child ends...\n");
waitpid(pid, NULL, 0);
printf("Parent ends\n");
}
int ret = munmap(shmem, sizeof(int)*4);
if( ret != 0 ){
fprintf(stderr, "Failed to unmap shared memory\n");
return -1;
}
return 0;
}
I've written a small piece of c code which you might find helpful:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#define NUM_INTS 5
int main(int argc, char *argv[])
{
key_t key = (key_t) 123456;
int shmgetrc, semgetrc;
struct shmid_ds ds;
int *shared_values;
int i;
struct sembuf sops[2];
int semid;
sops[0].sem_num = 0; /* Operate on semaphore 0 */
sops[0].sem_op = 0; /* Wait for value to equal 0 */
sops[0].sem_flg = 0;
sops[1].sem_num = 0; /* Operate on semaphore 0 */
sops[1].sem_op = 1; /* Increment value by one */
sops[1].sem_flg = 0;
/* create SHM segment */
shmgetrc = shmget(key, NUM_INTS * sizeof(int), IPC_CREAT | IPC_EXCL | 0x180);
if (shmgetrc < 0) {
perror("shmget failed...");
exit(1);
}
/* retrieve the address of the segment */
shared_values = (int *) shmat(shmgetrc, NULL, 0);
/* create a semaphore */
semgetrc = semget(key, 1, IPC_CREAT | IPC_EXCL | 0x180);
if (semgetrc < 0) {
perror("semget failed...");
exit(1);
}
/* lock the semaphore */
if (semop(semgetrc, sops, 2) == -1) {
perror("semop lock failed ...");
exit(1);
}
/* fill it with values */
for (i = 0; i < NUM_INTS; ++i) {
shared_values[i] = i;
}
/* unlock the semaphore */
sops[0].sem_op = -1;
if (semop(semgetrc, sops, 1) == -1) {
perror("semop release failed ...");
exit(1);
}
/* here something else could happen */
sleep(60);
/* lock the semaphore */
sops[0].sem_op = 0;
if (semop(semgetrc, sops, 2) == -1) {
perror("semop lock failed ...");
exit(1);
}
/* print values */
for (i = 0; i < NUM_INTS; ++i) {
printf("%d ", shared_values[i]);
}
printf("\n");
/* unlock the semaphore */
sops[0].sem_op = -1;
if (semop(semgetrc, sops, 1) == -1) {
perror("semop release failed ...");
exit(1);
}
/* remove the semaphore */
if (semctl(semgetrc, semgetrc, IPC_RMID) < 0) {
perror("semctl failed ...");
exit(1);
}
/* remove shm segment again */
if (shmctl(shmgetrc, IPC_RMID, &ds) < 0) {
perror("shmctl failed ...");
exit(1);
}
exit(0);
}
It was not my intention to write the most beautiful code ever written, just an example that shows:
how to create a shm segment
how to retrieve the address and to use it
how to remove it
Additionally, I've used a semaphore to protect the access.
Contrary to the other answer, I've used the ipc interface, not mmap().

Working with semaphores and shared memory under Linux

I need to write a program that is creating a N amount of sub processes and every single one of them adds one to a shared memory variable. My idea is to use semaphores and shared memory, but the processes are not waiting for each other and the shared memory variable is also not working as I want it.
mydefs.h
#ifndef __MYDEFS__H__
#define __MYDEFS__H__
// Includes
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <memory.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/shm.h>
#endif // __MYDEFS__H__
main.c
#include "mydefs.h"
#define PROC_COUNT 3
#define INITAL_MARKER_VALUE 0
#define PID_LEN 32
char mypid[PID_LEN];
int main()
{
int i, shm_id;
sem_t mutex;
if(sem_init(&mutex,1,1) < 0)
{
perror("semaphore initilization");
exit(0);
}
shm_id = shmget(IPC_PRIVATE, 4*sizeof(int), IPC_CREAT | 0666);
if (shm_id < 0) {
printf("shmget error\n");
}
int *shmpointer = shmat(shm_id,0,0);
memset(mypid, 0, sizeof(mypid));
sprintf(mypid, "%06d", getpid());
for(i = 0; i < PROC_COUNT; i++)
{
if (fork() == 0)
{
while(sem_wait(&mutex)!=0);
execl("slaveproc", "slaveproc", mypid, (char *)0);
shmpointer += 1;
sem_post(&mutex);
perror("\n Can't exec slave program. Cause ");
exit(1);
}
}
sleep(1);
printf("%d\n", *shmpointer);
return 0;
}
slaveproc.c
#include "mydefs.h"
int marker; // Marker value
int main(int argc, char *argv[])
{
master_pid = atoi(argv[1]);
printf("\n --------------------------------------");
printf("\n I'm the slave proc!");
printf("\n My pid: %d", getpid());
printf("\n My master's pid: %d", master_pid);
printf("\n --------------------------------------");
for(;;) pause();
return 0;
}
The problem (or at least "a problem") is that mutex is not in shared memory: it's allocated on the stack. When you fork(), the new process will have a completely separate copy from the old process, so calling sem_wait(&mutex) on one process will not affect the other process's mutex at all.
You should put mutex in the shared memory:
int main()
{
int i, shm_id;
shm_id = shmget(IPC_PRIVATE, sizeof(sem_t) + 4*sizeof(int), IPC_CREAT | 0666);
if (shm_id < 0) {
printf("shmget error\n");
}
int *shmpointer = shmat(shm_id,0,0);
sem_t *mutex = shmpointer;
shmpointer = (void*)shmpointer + sizeof(sem_t);
if(sem_init(mutex,1,1) < 0)
{
perror("semaphore initilization");
exit(0);
}
memset(mypid, 0, sizeof(mypid));
sprintf(mypid, "%06d", getpid());
for(i = 0; i < PROC_COUNT; i++)
{
if (fork() == 0)
{
while(sem_wait(mutex)!=0);
execl("slaveproc", "slaveproc", mypid, (char *)0);
shmpointer += 1;
sem_post(mutex);
perror("\n Can't exec slave program. Cause ");
exit(1);
}
}
sleep(1);
printf("%d\n", *shmpointer);
return 0;
}
You're also never writing to the memory in shmpointer (perhaps you meant (*shmpointer) += 1?), but I'll let you figure that out on your own.

What alternatives I have against sleep() to synchronize transfer between parent and child process?

I'm facing a synchronization problem, the problem I'm trying to solve involves sending string from parent to child, reversing it and sending it back to child ( using shared memory ).
However to make sure child is waiting for parent I'm using sleep(3) to give 3 seconds to parent process to enter string, however this is limiting my programs efficiency, I don't want to force user to wait for 3 seconds.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <sys/wait.h> /* Needed for the wait function */
#include <unistd.h> /* needed for the fork function */
#include <string.h> /* needed for the strcat function */
#define SHMSIZE 27
int main() {
int shmid;
char *shm;
if(fork() == 0) {
sleep(3);
shmid = shmget(29009, SHMSIZE, 0);
shm = shmat(shmid, 0, 0);
printf ("Child : Reading %s \n",shm) ;
int len=strlen(shm);
char rev[100],temp;
int i = 0;
int j = strlen(shm) - 2;
while (i < j) {
temp = shm[i];
shm[i] = shm[j];
shm[j] = temp;
i++;
j--;
}
shmdt(shm);
}else {
shmid = shmget(29009, SHMSIZE, 0666 | IPC_CREAT);
shm = shmat(shmid, 0, 0);
printf("Parent : Enter String \n ");
char *s = (char *) shm;
*s = '\0';
char a[100];
fgets(a,100,stdin);
strcat(s,a);
printf ("Parent: sending %s \n",shm);
sleep(3);
printf("Parent: receiving %s" ,shm);
shmdt(shm);
}
return 0;
}
Question:
How could this be implemented in a better way, so that the program is more efficient?
I would suggest using semaphores, this is not a case where you use 'sleep':
http://man7.org/linux/man-pages/man7/sem_overview.7.html
You can use them like in this example:
http://www.csc.villanova.edu/~mdamian/threads/posixsem.html
You cannot know for sure that it will not take more than 3 seconds, so sleep is a realy bad choice. So, it goes something like this:
#include <stdio.h>
#include <semaphore.h>
int main(void)
{
sem_t *sem = mmap(0, sizeof(sem_t), PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_ANONYMOUS, -1, 0);
sem_init(sem, 1, 1);
if(fork() == 0) {
printf("Child: Waiting to acquire semaphore\n");
sem_wait(sem);
printf("Child acquires lock\n");
/* do whatever you want then relese*/
sem_post(sem);
} else {
printf("Parent: Waiting to acquire semaphore\n");
sem_wait(sem);
printf("Parent acquires lock\n");
/* do whatever you want then relese*/
sem_post(sem);
}
sem_destroy(sem);
return 0;
}
Oh and if you want it parent to be followed by child always (or the other way around), you can use two semaphores, and initialize them accordingly(with 1 and 0, or 0 and 1).
sem_wait(sem1);
printf("Parent acquires lock\n");
/* do whatever you want then relese*/
sem_post(sem2);
/* Other things will be happening here */
sem_wait(sem2);
printf("Child acquires lock\n");
/* do whatever you want then relese*/
sem_post(sem1);
Edit
If you do not have to use shared memory, it would be better to do the communication with sockets.
Thanks to amazing StackOverflow community for coming to my rescue! I have resolved solved the issue using semaphores! I'm sharing my final code so it can be of use for anyone who gets struck in a situation like mine!
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <sys/wait.h> /* Needed for the wait function */
#include <unistd.h> /* needed for the fork function */
#include <string.h> /* needed for the strcat function */
#include <semaphore.h>
#include <sys/mman.h>
#include<fcntl.h>
#include<stdlib.h>
#define SHMSIZE 27
typedef struct {
sem_t one;
sem_t two;
} SemPair;
int main() {
int shm = shm_open("/test", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
ftruncate(shm, sizeof(sem_t));
SemPair *sem = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
sem_init(&(sem->one), 1, 0);
sem_init(&(sem->two), 1, 0);
int shmid;
char *shmz;
if(fork() == 0) {
sem_wait(&(sem->one));
shmid = shmget(29009, SHMSIZE, 0);
shmz = shmat(shmid, 0, 0);
printf ("Child : Reading %s \n",shmz) ;
int len=strlen(shmz);
char rev[100],temp;
int i = 0;
int j = strlen(shmz) - 2;
while (i < j) {
temp = shmz[i];
shmz[i] = shmz[j];
shmz[j] = temp;
i++;
j--;
}
shmdt(shmz);
sem_post(&(sem->two));
}
else {
shmid = shmget(29009, SHMSIZE, 0666 | IPC_CREAT);
shmz = shmat(shmid, 0, 0);
printf("Parent : Enter String \n ");
char *s = (char *) shmz;
*s = '\0';
char a[100];
fgets(a,100,stdin);
strcat(s,a);
printf ("Parent: sending %s \n",shmz);
sem_post(&(sem->one));
sem_wait(&(sem->two));
printf("Parent: receiving %s" ,shmz);
shmdt(shmz);
}
return 0;
}

Shared memory linux

I'm trying to work with shared memory at the first time. I created one child process and I write to the shared memory from Parent and change it from Child, before program ends I print shared memory from Parent and shared memory hasn't change, here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <signal.h>
sem_t *semaphore;
int main(){
int i = 0, status;
pid_t pid=fork(), w;
int id;
if ((id = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0666)) == -1){
perror("shmget");
exit(1);
}
int *sh;
if ((sh =(int *) shmat(id, NULL, 0)) == NULL){
perror("shmat");
exit(1);
}
*sh = 10;
if ((semaphore = sem_open("/semaphore", O_CREAT, 0666, 0)) == SEM_FAILED){
perror("semaphore");
exit(1);
}
if (pid==0) {
while(1){
sleep(1);
*sh = 50;
printf("child %d, %d\n", i, *sh);
i++;
if(i == 5){
sem_post(semaphore);
exit(0);
}
}
} else if (pid==-1) {
perror("process error\n");
} else {
printf("Parent, %d\n", *sh);
sem_wait(semaphore);
printf("child end => parent end\n");
printf("Parent, %d\n", *sh);
}
shmctl(id, IPC_RMID, NULL);
sem_close(semaphore);
sem_unlink("/semaphore");
return 0;
}
If I understand shared memory little bit than I can change it from everywhere if I have a pointer in my case is a "sh".
Output of program is:
Parent, 10
child 0, 50
child 1, 50
child 2, 50
child 3, 50
child 4, 50
child end => parent end
Parent, 10
Why is the number in shared memory different in Parent and in Child?
You fork() before you create the shared memory with the key IPC_PRIVATE, so both processes create their own shared memory and don't actually share it.
If you remove the =fork() from
pid_t pid=fork(), w;
and insert
pid = fork();
somewhere after the shmget call, it works the way you expect, since the child process will inherit the shared memory identifier from the parent and not create a different one.

C: parallel processes and pick the last but one

I have to write a program in C that uses processes, not threads (I'm writing in UNIX):
the father generate 7 children.
every child generate a random integer and begin an empty for statement from 0 to that random int.
at the end, the father calls wait and print the pid of the last but one process that has terminated.
this is what I'm trying:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/shm.h>
#include <sys/ipc.h>
int main(){
int n = 7;
int i,r, random;
pid_t pid;
pid_t pid_padre;
int *shared_memory;
int segment_id;
int size = 1024;
int ciclo;
pid_padre = getpid();
printf("Inizio programma:\n");
printf("Processo Padre: [%d]\n", pid_padre);
segment_id = shmget(IPC_PRIVATE, size, S_IRUSR | S_IWUSR);
shared_memory = shmat(segment_id, NULL, 0);
for(i=0;i<n;i++) {
shared_memory[i] = 0;
}
for(i=0;i<n;i++) {
pid =fork();
if (pid == 0) {
random = rand();
for(ciclo=0; ciclo<random; ciclo++);
for (r=0; r<n; r++) {
if (shared_memory[r] == 0) {
//printf("figlio %d\n",getpid() );
//shared_memory[r] = (int)getpid();
break;
}
}
break;
}
}
if (getpid() == pid_padre) {
wait(NULL);
//sleep(3);
for(i=0;i<n;i++) {
printf("array, figlio %d, pid \n",i , shared_memory[i]);
}
shmdt(shared_memory);
shmctl(segment_id, IPC_RMID, NULL);
}
return 0;
}
edit: what's wrong in my code: at the end, it does print nothing instead of pids, it prints
"array, figlio 1, pid "
instead of "array, figlio 1, pid 3898" for example

Resources