UNIX Shared Memory [duplicate] - c

I have been working on semaphores and shared memory for a week now, and have some difficulties yet,so i tried to make this program which the children are supposed to write to a memory shared multidimensional integer array and the father is suppose to read that array from the memory that is shared.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <semaphore.h>
#include <sys/wait.h>
#define MAXCHILDS 1
#define MAX_SIZE 10
#define MAX_WRITES 100
typedef struct{
int m[MAX_SIZE][MAX_SIZE];
}matrix;
/*fork variables*/
pid_t child[MAXCHILDS];
/*semphores variables */
sem_t *empty, *full, * mutex;
/*share memory id*/
int shmid;
/*shared memory array pointer */
matrix * sh_mem;
void init(){
/*semaphores unlink and creation */
sem_unlink("EMPTY");
empty=sem_open("EMPTY",O_CREAT|O_EXCL,0700,50);
sem_unlink("FULL");
full=sem_open("FULL",O_CREAT|O_EXCL,0700,0);
sem_unlink("MUTEX");
mutex=sem_open("MUTEX",O_CREAT|O_EXCL,0700,1);
/*initialize shared memory */
shmid = shmget(IPC_PRIVATE,sizeof(matrix),IPC_CREAT|0777);
/*map shared memory*/
sh_mem = (matrix*)shmat(shmid,NULL,0);
if(sh_mem == (matrix*)(-1)){
perror("shmat");
}
}
void writer(int m[MAX_SIZE][MAX_SIZE],int n_child){
int i,k;
for(i = 0;i<MAX_SIZE;i++){
for(k= 0;k<MAX_SIZE;k++){
m[i][k] = 0;
if(i==(k+1)){
m[i][k] = 1;
}
}
}
}
void reader(int m[MAX_SIZE][MAX_SIZE]){
int i = 0;
int k = 0;
int sum = 0;
for(i = 0;i<MAX_SIZE;i++){
for(k= 0;k<MAX_SIZE;k++){
printf("%d",m[k][i]);
}
sum++;
printf("[i=]%d[k=]%d\n",i,k);
}
printf("%d",sum);
}
void terminate() {
sem_close(empty);
sem_close(full);
sem_close(mutex);
sem_unlink("EMPTY");
sem_unlink("FULL");
sem_unlink("MUTEX");
shmctl(shmid, IPC_RMID, NULL);
}
int main(int argc, char **argv)
{
int i,sum;
init();
for(i = 0;i<MAXCHILDS;i++){
if((child[i]= fork()) < 0) // error occured
{
perror("Fork Failed");
exit(1);
}
if((child[i] =fork())==0){
writer(sh_mem->m,i);
exit(0);
}
}
/*father*/
sleep(10);
sum++;
printf("%d\n",sum);
reader(sh_mem->m);
wait(NULL);
terminate();
return 0;
}
I have two problems right now ... I need to save the array to a memory mapped file which i dont seem to understand and the output of the father is throwing is very strange ...His output is
0000100000[i=]3[k=]10
0000010000[i=]4[k=]10
0000001000[i=]5[k=]10
0100000000[i=]0[k=]10
0000000100[i=]6[k=]10
0010000000[i=]1[k=]10
0000000010[i=]7[k=]10
0001000000[i=]2[k=]10
0000000001[i=]8[k=]10
0000100000[i=]3[k=]10
0000000000[i=]9[k=]10
0000010000[i=]4[k=]10
0000001000[i=]5[k=]10
0000000100[i=]6[k=]10
0000000010[i=]7[k=]10
0000000001[i=]8[k=]10
0000000000[i=]9[k=]10
And it should be something like this:
0000100000[i=]0[k=]10
0000010000[i=]1[k=]10
0000001000[i=]2[k=]10
0100000000[i=]3[k=]10
0000000100[i=]4[k=]10
0010000000[i=]5[k=]10
0000000010[i=]6[k=]10
0001000000[i=]7[k=]10
0000000001[i=]8[k=]10
0000100000[i=]9[k=]10

The code calls fork() in two places. Remove the second call.
Change:
if((child[i] =fork())==0){
to:
if(child[i] == 0){

Related

Getting bad address when I fork?

So I have three files: Pellets.c, Fish.c, and SwimMill.c. SwimMill calls Pellets and Fish, which should fork. However, when I try to fork Pellets, i get an error saying "Pellet fork failed: Bad Address". Anyone know what the problem is?
include.h
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#define SHM_SIZE 1000
int shmid;
int *shm;
pid_t fish;
pid_t pellet;
void attachSharedMemory() {
key_t key = ftok("SwimMill.c", 'b'); //generate random key
shmid = shmget(key, SHM_SIZE, IPC_CREAT|0666);
shm = shmat(shmid, NULL, 0);
}
SwimMill.c
// Uses both fish and pellets, 30 seconds, then print it out
// Create pellets at random intervals, from 0x80
// Eating --> Get rid of most significant bit
// Use shared memory for fish and pellet position only
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include "include.h"
#define SHM_SIZE 1000
void printGrid(int*);
void handler(int);
void killProgram(pid_t, pid_t, int*, int);
pid_t fish;
pid_t pellet;
int main(int argc, char* argv[]) {
int timer = 0;
attachSharedMemory(); // from include.h
signal(SIGINT, handler);
// Initializing the shared memory to prevent segmentation fault
// for (int i = 0; i < SHM_SIZE; i++){
// shm[i] = -1;
// }
srand(time(NULL));
fish = fork();
if (fish == -1) {
perror("Fish fork failed1");
exit(1);
} else if (fish == 0) {
execv("Fish", argv);
perror("Fish exec failed");
exit(1);
}
while(timer <= 30){
pellet = fork();
if (pellet == -1) {
perror("Pellet Fork failed1");
exit(1);
} else if (pellet == 0) {
execv("Pellets", argv);
perror("Pellets Fork failed");
exit(1);
}
printGrid(shm);
sleep(1);
printf("Timer: %d\n", timer);
timer++;
}
killProgram(fish, pellet, shm, shmid);
getchar(); // Pause consol
return 0;
}
void printGrid(int* shm) {
int row = 10;
int column = 10;
char (*stream)[row][column]; //2D Dimensional array, fish can only move last row of 2d
//Initializing grid first
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
(*stream)[i][j] = '~';
}
}
printf("Fish: %d \n", shm[0]);
printf("Shm2 is: %d \n", shm[1] );
for (int k = 1; k < 20; k++) {
(*stream)[shm[k]/10][shm[k]%10] = 'O'; // pellets
}
(*stream)[shm[0]/10][shm[0]%10] = 'Y'; // Fish
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
printf("%c ", (*stream)[i][j]);
}
printf("\n");
}
}
void killProgram(pid_t fish, pid_t pellet, int *shm, int shmid) {
kill(fish,SIGUSR1);
kill(pellet, SIGUSR1);
sleep(5);
shmdt(shm);
shmctl(shmid, IPC_RMID, NULL);
printf("Program finished! \n");
}
void handler(int num ) {
kill(fish,SIGUSR1);
kill(pellet, SIGUSR1);
shmdt(shm);
shmctl(shmid, IPC_RMID, NULL);
perror(" Interrupt signal is pressed!! \n");
exit(1);
}
Pellets.c
// Multiple pellets
//Process ID, position, eaten/misse
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include "include.h"
#define SHM_SIZE 1000
void handler(int);
void eatPellet();
void missPellet();
int main(int argc, char* argv[]) {
signal(SIGINT, handler);
attachSharedMemory();
srand(time(NULL));
int i = 1; // 1 - 19 are pellets
for (; i < 20; i++) {
int pelletPosition = rand() % 9 ; // random number from 0 - 9
if (shm[i] == -1){
// printf("hello %d \n", pelletPosition);
shm[i] = pelletPosition;
}
break;
}
while(1) {
printf("helloasd %d \n", shm[i]);
printf("i: %d \n", i);
if (shm[i] < 90) {
shm[i] += 10;
}
else if (shm[i] == shm[0]) {
eatPellet();
printf("Position: %d\n", shm[i] );
break;
// EATEN and KILL
}
else {
// KIll process, terminate
missPellet();
printf("Position: %d\n", shm[i] );
break;
}
// printf("%d\n",shm[i] );
i++;
sleep(1);
}
shmdt(shm);
return 0;
}
void handler(int num) {
shmdt(shm);
exit(1);
}
I looked at other stack overflow questions, and it seems that they problems because they didn't terminate with a NULL? I think the problem lies inside Pellets.c, but I can't seem to figure it out. Thanks.

Calculate sum from 1 to 2000 using child process in shared memory in linux

I have a problem that i have to calculate sum from 1 to 2000 using child process. Here is my code:
#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;
int tong1=0;
int tong2=0;
if(fork() == 0) {
shmid = shmget(2009, SHMSIZE, 0);
shm = shmat(shmid, 0, 0);
int i;
for(i=0; i<1000; i++) {
tong1=tong1+i;
}
shmdt(shm);
}
else {
shmid = shmget(2009, SHMSIZE, 0666 | IPC_CREAT);
shm = shmat(shmid, 0, 0);
wait(NULL);
int j;
for(j=1000; j<=2000; i++) {
tong2=tong2+j;
}
shmdt(shm);
shmctl(shmid, IPC_RMID, NULL);
}
int tong=0; tong=tong1+tong2;
printf("Sum is: %d",tong);
return 0;
}
But when i run the result is: Sum is 499500 Sum is 1501500. Where am i wrong?
because in second cycle, you do i++ instead of j++
for(j=1000; j<=2000; i++) { // <== should be j++
tong2=tong2+j;
}
You're creating a shared memory segment, but you aren't using it for anything! Simply creating a shared memory segment doesn't cause local variables to be shared between processes -- you need to actually read and write to the shared memory.

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.

Using semaphores with shared memory while running multiple processes

I am learning some simple producer/consumer examples involving semaphores, but having a hard time explaining to myself why I am getting a certain result (because I am a noobie to C).
When I run two concurrent processes of the following producer, both processes get hung up and never finish:
#include <stdio.h>
#include <sys/types.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#define BUFF_SIZE 20
typedef struct {
char buffer[BUFF_SIZE];
int nextIn;
int nextOut;
} shared_data;
shared_data *shm, *s;
char sem_name1[] = "mutex";
char sem_name2[] = "empty_slots";
char sem_name3[] = "full_slots";
sem_t *empty_slots;
sem_t *full_slots;
sem_t *mutex;
void Put(char item)
{
sem_wait(empty_slots);
sem_wait(mutex);
s->buffer[s->nextIn] = item;
s->nextIn = (s->nextIn + 1) % BUFF_SIZE;
sem_post(mutex);
printf("Producing %c ... with pid = %d\n", item, getpid());
sem_post(full_slots);
}
void Producer()
{
int i;
for(i = 0; i < 10; i++)
{
sleep(rand()%3);
Put((char)('A'+ i % 26));
}
}
void main()
{
//Create and initialize the semaphores
mutex=sem_open(sem_name1, O_CREAT,0644, 1);
full_slots=sem_open(sem_name3, O_CREAT,0644, 0);
empty_slots=sem_open(sem_name2, O_CREAT,0644, 10);
//Create a key for the segment
key_t key;
key = 1234;
//create the segment
int shmid;
if ((shmid = shmget(key, sizeof(shared_data), IPC_CREAT |0666)) <0)
{
perror("Shmget");
exit(1);
}
//attach to the segment
if ((shm = (shared_data *) shmat(shmid, NULL, 0))==(shared_data *) -1)
{
perror("Shmat");
exit(1);
}
s=shm;
s->nextIn = 0;
Producer();
//detach from the segment
shmdt((void *) shm);
}
The output from the first and second processes, respectively:
Can someone help me understand why this happens (i.e. why do these processes never finish)? Have I created a deadlock? Why or why not? I am completely stumped.
Thanks!

Unix Programming Shared Memory strange results

I have been working on semaphores and shared memory for a week now, and have some difficulties yet,so i tried to make this program which the children are supposed to write to a memory shared multidimensional integer array and the father is suppose to read that array from the memory that is shared.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <semaphore.h>
#include <sys/wait.h>
#define MAXCHILDS 1
#define MAX_SIZE 10
#define MAX_WRITES 100
typedef struct{
int m[MAX_SIZE][MAX_SIZE];
}matrix;
/*fork variables*/
pid_t child[MAXCHILDS];
/*semphores variables */
sem_t *empty, *full, * mutex;
/*share memory id*/
int shmid;
/*shared memory array pointer */
matrix * sh_mem;
void init(){
/*semaphores unlink and creation */
sem_unlink("EMPTY");
empty=sem_open("EMPTY",O_CREAT|O_EXCL,0700,50);
sem_unlink("FULL");
full=sem_open("FULL",O_CREAT|O_EXCL,0700,0);
sem_unlink("MUTEX");
mutex=sem_open("MUTEX",O_CREAT|O_EXCL,0700,1);
/*initialize shared memory */
shmid = shmget(IPC_PRIVATE,sizeof(matrix),IPC_CREAT|0777);
/*map shared memory*/
sh_mem = (matrix*)shmat(shmid,NULL,0);
if(sh_mem == (matrix*)(-1)){
perror("shmat");
}
}
void writer(int m[MAX_SIZE][MAX_SIZE],int n_child){
int i,k;
for(i = 0;i<MAX_SIZE;i++){
for(k= 0;k<MAX_SIZE;k++){
m[i][k] = 0;
if(i==(k+1)){
m[i][k] = 1;
}
}
}
}
void reader(int m[MAX_SIZE][MAX_SIZE]){
int i = 0;
int k = 0;
int sum = 0;
for(i = 0;i<MAX_SIZE;i++){
for(k= 0;k<MAX_SIZE;k++){
printf("%d",m[k][i]);
}
sum++;
printf("[i=]%d[k=]%d\n",i,k);
}
printf("%d",sum);
}
void terminate() {
sem_close(empty);
sem_close(full);
sem_close(mutex);
sem_unlink("EMPTY");
sem_unlink("FULL");
sem_unlink("MUTEX");
shmctl(shmid, IPC_RMID, NULL);
}
int main(int argc, char **argv)
{
int i,sum;
init();
for(i = 0;i<MAXCHILDS;i++){
if((child[i]= fork()) < 0) // error occured
{
perror("Fork Failed");
exit(1);
}
if((child[i] =fork())==0){
writer(sh_mem->m,i);
exit(0);
}
}
/*father*/
sleep(10);
sum++;
printf("%d\n",sum);
reader(sh_mem->m);
wait(NULL);
terminate();
return 0;
}
I have two problems right now ... I need to save the array to a memory mapped file which i dont seem to understand and the output of the father is throwing is very strange ...His output is
0000100000[i=]3[k=]10
0000010000[i=]4[k=]10
0000001000[i=]5[k=]10
0100000000[i=]0[k=]10
0000000100[i=]6[k=]10
0010000000[i=]1[k=]10
0000000010[i=]7[k=]10
0001000000[i=]2[k=]10
0000000001[i=]8[k=]10
0000100000[i=]3[k=]10
0000000000[i=]9[k=]10
0000010000[i=]4[k=]10
0000001000[i=]5[k=]10
0000000100[i=]6[k=]10
0000000010[i=]7[k=]10
0000000001[i=]8[k=]10
0000000000[i=]9[k=]10
And it should be something like this:
0000100000[i=]0[k=]10
0000010000[i=]1[k=]10
0000001000[i=]2[k=]10
0100000000[i=]3[k=]10
0000000100[i=]4[k=]10
0010000000[i=]5[k=]10
0000000010[i=]6[k=]10
0001000000[i=]7[k=]10
0000000001[i=]8[k=]10
0000100000[i=]9[k=]10
The code calls fork() in two places. Remove the second call.
Change:
if((child[i] =fork())==0){
to:
if(child[i] == 0){

Resources