When I run shmget in the following code it is returning a value of -1 and im not sure why that is the case. Everything else seems to be running fine. The code is just supposed to take in a few digits from the command line and then create shared memory for them. The digits will range from 0 to 9.
#include <sys/ipc.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <sys/types.h>
int main(int argc, char *argv[])
{
int numArgc =(int)argc-1; //number of vauled arguments passed
int arrayId[numArgc];
pid_t pid;
int arrSpace[numArgc]; //array to store atoi of values
int status;
int *memory; //pointer to shared memory
int memoryId; //check for smhget
int childPID;
int childId;
if(argc > 8 || argc < 2) //check number of cmd line arg
{
printf("The number of arguments must be between 1 and 7");
return(0);
}
else
{
for(int i=1; i<numArgc+1; i++) //store args as integers
{
arrSpace[i]=atoi((argv[i]));
printf("%d\n", arrSpace[i]);
}
}
memoryId=shmget(IPC_PRIVATE, try, IPC_CREAT | 07546); //create shared
printf("%d \n", memoryId);
if(memoryId<0)
{
printf("There was an error with ID.\n");
return (0);
}
printf("%s%d", "Size of shared Memory of parent is \n ", numArgc);
memory=(int*)shmat(memoryId, NULL, 0); // attaches shared memory
if((long)memory == -1)
{
printf("There was an error running shmat .\n");
return (0);
}
printf("Share memory is now: \n");
for(int i=0; i<numArgc; i++)
{
memory[i]=arrSpace[i];
}
printMemory(memory, numArgc);
printf("Beginning fork process");
for(childId; childId <= numArgc; childId++)
{
pid = fork(); //creates new process
if(pid < 0)
{
printf("There was an error during fork process");
return (0);
}
else if(pid == 0)
{
ChildProcess(memory, numArgc, childId);
exit(0);
}
}
ParentProcess(memory, childPID, numArgc, memoryId, status);
return (0);
}
shmget returns -1 because try variable is undefined and the permission 07546 is invalid.Please pass appropriate permission for the memory segment.
#define MEMORY_SIZE 20 //size of memory segment
memoryId=shmget(IPC_PRIVATE, MEMORY_SIZE , IPC_CREAT | 0666); //create shared
printf("%d \n", memoryId);
Related
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().
What I have to do:
-Create a shared memory segment.
-fill an array with a fixed number of integers e.g 100
-pass these created numbers to a child process in blocks of 10 each.
-in the child process: output these numbers
So this is basically a communication between two processes via a shared memory segment.
My question: So far I can pass the first 10 numbers to the child process .. but I don't really know how to pass the next 10 numbers to the very same child process to output it without creating more child processes .. I thought maybe I could simply wrap everything in a while loop but then everytime a new child process is created which is not what I want.
Right now I have the following Code:
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define N_SHARED 10
#define SIZE 100
int main(int argc, char **argv){
int shID;
int *myPtr;
int i;
int counter = 0;
int array[SIZE];
for(i=0;i<SIZE;i++){
array[i] = lrand48();
}
/* Shared Memory Creation */
shID = shmget(223520, N_SHARED, IPC_CREAT | 0666);
if (shID >= 0) {
/* get memory */
myPtr = shmat(shID, 0, 0);
if (myPtr==(int *)-1) {
perror("shmat");
} else {
/* memory is accessible */
for (i=0; i<N_SHARED; i++) {
myPtr[i] = array[counter];
counter += 1;
}
// create Child Process
pid_t child = fork();
if(child == 0){
sleep(5);
shID = shmget(223520, N_SHARED, 0666);
if (shID >= 0) {
myPtr = shmat(shID, 0, 0);
if (myPtr==(int *)-1) {
perror("shmat");
} else {
for (i=0; i<N_SHARED; i++) {
printf("%d\n", myPtr[i]);
}
shmdt(myPtr);
}
}else {
/* shmget went wrong */
perror("shmget");
}
}
/* give up memory */
shmdt(myPtr);
}
} else {
/* shmget went wrong */
perror("shmget");
}
}
I have 2 processes running test.c. There is a signal handler in test.c which executes an execlp. In test.c, I have a static variable which needs to be only initialized once, and incremented each time before the execlp call. When either process reaches 99, they exit.
Unfortunately, right now, it's not getting incremented, my guess is because there are 2 processes that each have a copy of the static variable. Here is test.c:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
static int i = 0;
static int foo(int j)
{
printf("In the foo...\n");
j++;
printf("%d\n", j);
return j;
}
void main(int argc, char *argv[])
{
int pid, pid2, k;
int *h = malloc(sizeof(int));
int g = 0;
h = &g;
static char s[15];
pid = fork();
if (pid > 0)
{
sleep(1);
}
if (pid == 0)
{
k = foo(*h);
sprintf(s, "%d", k);
if (k >= 99)
{
printf("k=99\n");
exit(0);
}
execlp("./a.out", "forktest", s, NULL);
}
pid2 = fork();
if (pid2 == 0)
{
k = foo(*h);
sprintf(s, "%d", k);
if (k >= 99)
{
printf("k=99\n");
exit(0);
}
execlp("./a.out", "forktest", s, NULL);
}
wait(pid2);
wait(pid);
}
Can anyone please explain why there is an infinite loop? Why isn't the static variable get incremented?
Thank you.
Use Interprocess communication concepts (pipe, fifo, shared memory) here, execlp function overwrites memory of current program with new program. So when ever you call execlp gets called your program get refreshed and starts from begining and static int i is always 0.
I recommend to use pipe Refer this.
You need to use memory projection (mmap function) if you want to use the concept of shared memory between process.
In your code, the variable 'h' is the shared variable between the three process.It should defined using mmap function and initialized in the main process and then incremented in the two child process.
The answers to your two questions are related: either of the two child process never exits (exit(0)) because the if(k>=99) is never statisfied. This is due to the non-shared variable h which doesn't get incremented.
I will rather use a while loop and a return type main function.
By the way, you don't need the 'g' varibale, you can initialize directly 'h'. And there is no need of declaring the function foo as static (static functions are only useful when you want them to visible only with the file where they are defined). The buffer 's' can be declared non static (it is only a buffer which contains the value of k)
Here is a modified version of your code, it compiles and works fine.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
int foo(int* j)
{
printf("In the foo...\n");
(*j)++;
printf("%d\n", *j);
return *j;
}
int main(void)
{
int pid, pid2, k;
char s[15];
int * h = (int*)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (h == MAP_FAILED) {
printf("map failed\n");
return -1;
}
*h = 0;
pid = fork();
if (pid < 0) {
printf("fork failed pid\n");
return -1;
}
if (pid > 0) {
sleep(1);
}
else {
while(1) {
k = foo(h);
sprintf(s, "%d", k);
if (k>=99) {
printf("k>=99\n");
printf("%s\n", s);
exit(0);
}
execlp("./a.out", "forktest", s, NULL);
}
}
pid2 = fork();
if (pid2 < 0) {
printf("fork failed pid2\n");
}
if (pid2 > 0) {
sleep(1);
}
else {
while(1) {
k = foo(h);
sprintf(s, "%d", k);
if (k>=99) {
printf("k>=99\n");
exit(0);
}
execlp("./a.out", "forktest", s, NULL);
}
}
wait(pid);
wait(pid2);
return 0;
}
Here is the output (only the last strings) click on the link:
output
I've been stuck on getting piping to work between two programs for the last couple of hours and I'm stuck and not sure if I'm doing something wrong. The idea of my program is that I'm going to use interface.c to open a pipe, and then execute db.c. I want to use two pipes to communicate between the two different programs. Now, with interface.c being the 'parent' and db.c being the 'child', I'm not sure if I'm passing in the parameters to my pipe correctly via the execl command. Everything compiles correctly, but when I try to run the interface program, I'm getting an error stating: 'Bad File Number.' Is it possible that I'm not using pipes correctly? Currently, I'm just trying to get my program to send an integer, value, over the pipe to db.c. Any help would be much appreciated.
Code for interface.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/wait.h>
//PIPES:
//
//Parent: reads from P1_READ, writes on P1_WRITE
//Child: reads from P2_READ, writes on P2_WRITE
#define P1_READ 0
#define P2_WRITE 1
#define P2_READ 2
#define P1_WRITE 3
// the total number of pipe *pairs* we need
#define NUM_PIPES 2
int main(int argc, char *argv[])
{
//Create Pipe Array
int fd[2*NUM_PIPES];
//For Parameter Passing:
char param0[20]; //P1_Read
char param1[20]; //P2_Write
char param2[20]; //P2_Read
char param3[20]; //P1_Write
snprintf(param0, sizeof(param0), "%d" , fd[0]);
snprintf(param1, sizeof(param1), "%d" , fd[1]);
snprintf(param2, sizeof(param2), "%d" , fd[2]);
snprintf(param3, sizeof(param3), "%d" , fd[3]);
//Variables
pid_t pid;
int val = 42;
//Allocate the PIPES
for (int i=0; i<NUM_PIPES; ++i)
{
if(pipe(fd+(i*2)) < 0)
{
perror("Failed to allocate the pipes");
exit(EXIT_FAILURE);
}
}
//If the fork of the program does not work:
if ((pid = fork()) < 0)
{
perror("Failed to fork process");
return EXIT_FAILURE;
}
if(pid == 0)
{ //Child Process
execl("./db", "db", param0, param1, param2, param3, (char *)NULL);
}
else
{ //Parent Process
//SENDING VALUES HERE
close(fd[P2_READ]);
close(fd[P2_WRITE]);
printf("Interface is sending|%d| to DB\n", val);
if(write(fd[P1_WRITE],&val, sizeof(val)) != sizeof(val))
{
perror("Interfae failed to send value to DB");
exit(EXIT_FAILURE);
}
}
return 0;
}
This is for db.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>
//Typedef-Class-
typedef struct Information
{
int accountId;
int checkNumber;
int date;
float amount;
} Information;
int main(int argc, char *argv[])
{
//For Input
//Account Data
Information acctData[25];
int dataStorageLooper = 0; //How many db entries
//For File Input
int aVal;
int bVal;
int cVal;
float dVal;
//Prepare for file input:
FILE * fp;
fp = fopen ("accountData.txt", "r");
//Reads Input
while(1)
{
if (fscanf(fp, "%d %d %d %f", &aVal, &bVal, &cVal, &dVal)!=4)
{
break;
}
//Puts data into appropriate arrays
acctData[dataStorageLooper].accountId= aVal;
acctData[dataStorageLooper].checkNumber= bVal;
acctData[dataStorageLooper].date= cVal;
acctData[dataStorageLooper].amount= dVal;
dataStorageLooper++;
}
//Decrement index to point to last item
dataStorageLooper--;
//Displays all values
printf("\nDisplaying AccountData.txt\n");
for( int i = 0; i < dataStorageLooper; i++)
{
printf("Line|%d|: Account|%d|: Check|%d|: Date|%d|: Amount|%.2f|\n",i,acctData[i].accountId,acctData[i].checkNumber,acctData[i].date,acctData[i].amount);
}
//Closes File
fclose(fp);
//End Input
//Parameter Receiving:
int pipes[4]; //Pipe Array
int value = 7;
int test;
//Build the pipes
pipes[0] = atoi(argv[1]); //P1_Read
pipes[1] = atoi(argv[2]); //P2_Write
pipes[2] = atoi(argv[3]); //P2_Read
pipes[3] = atoi(argv[4]); //P1_Write
//Troubleshooting
printf("The number of parameters: %d\n",argc);
printf("Parameter 1: %s\n", argv[0]);
printf("I stared correctly\n");
//Testing
close(pipes[0]);
close(pipes[3]);
//SHOULD RECEIVE VALUE HERE
test = read(pipes[2], &value, sizeof(value));
if (test < 0)
{
perror("DB: Failed to read data from parent");
exit(EXIT_FAILURE);
}
else if (test == 0)
{
//Unexpected
fprintf(stderr, "DB: Read End-Of-File from pipe");
}
else
{
//What did the child receive?
printf("DB: Received Value:(%d)\n", value);
}
close(pipes[2]);
close(pipes[1]);
return 0;
}
One of the things you're doing wrong is snprintfing the value of the various elements in fd before you've assigned any value to them. That's undefined behaviour, and the values you're passing as parameters are totally meaningless (at best).
This strikes me as a very odd way to do things, though. Usually you would just dup2 fds 0 and 1 so that the child's stdin and stdout are redirected to the appropriate pipe fds.
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.