memory and pass values in a Pointer in shared memory - c

I'm trying to pass some values between a parent and 10 child processes with shared memory and active wait.
Some values in the struct are pointers to allocate outside dynamic memory
The error is showing when i'm trying to write a number in a string to pass a path file with numbers, but I can't since the memory is not there, I can only do it without a number.
typedef struct {
char *path[10];
char *word[10];
int number_ocurrency[10];
int flag[10];
} shared_data_type;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[]) {
int fd;
int data_size = sizeof(shared_data_type),i;
pid_t pid;
shared_data_type *shared_data;
if((fd = shm_open("/ex06_searchWord", O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR))==-1)
{
perror("Error at shared memory allocation!\n");
return 0;
}
ftruncate (fd, data_size);
shared_data = (shared_data_type *)mmap(NULL,data_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
for(i=0; i<10;i++){
shared_data->flag[i]=0;
pid=fork();
if (pid == -1)
{
printf("Error at fork!\n");
return -1;
}
if (pid == 0) { /* reader */
while(!shared_data->flag[i]);
FILE *file;
file = fopen(shared_data->path[i], "r");
if (file == NULL)
{
printf("Could not open/find the specified file.\n");
return -1;
}
int size = 0;
char readChar=NULL;
char *msg = NULL;
while((readChar = fgetc(file)) != EOF) {
msg = (char *) realloc(msg, size+1);
*(msg + size) = readChar;
size++;
}
*(msg + size) = '\0';
int count = 0;
while(msg = strstr(msg, shared_data->word[i]))
{
count++;
msg++;
}
shared_data->number_ocurrency[i]=count;
exit(0);
}
if(pid>0){
shared_data->word[i]="SCOMP";
char path[16]="files/file1.txt";
shared_data->path[i]=malloc(sizeof(path)+1);
sprintf(shared_data->path[i],"files/file%d.txt",i);
//shared_data->path[i]= "files/file.txt";
shared_data->number_ocurrency[i]=0;
shared_data->flag[i]=1;
}
}
for(i=0; i<10;i++){
wait(NULL);
}
for(i=0; i<10;i++){
printf("The word %s in the son %d appeared: %d times\n",shared_data->word[i],i,shared_data->number_ocurrency[i]);
}
if (munmap(shared_data, data_size) == -1)
{
perror("Error at unmap!\n");
return 0;
}
if(shm_unlink("/ex06_searchWord")==-1){
perror("Error at unlink!\n");
return 0;
}
return 0;
}

When you share bytes between processes, you need to make sure those bytes contain something that is meaningful and understandable to all the processes that are going to use it. Putting pointers to memory that isn't shared in shared memory makes no sense. And unless all the processes can be guaranteed to map the shared memory at the same address, even putting absolute pointers to shared memory in shared memory makes no sense.
You can divide the shared memory into "slots" if you want and get the effect of having pointers in shared memory by placing the slot number in shared memory. The slot number will have to be translated to and from an absolute address in each process, taking into account the base address of the mapping.

Related

Reading in non-ASCII characters into a buffer

I have a multi-process program that receives a file as input from the command line. Creates shared memory, and forks for a producer/consumer styled problem. It switches every other byte making abcdef badcef. However, I had not realized this must also allow for non-ASCII input, and I do not know how to do this. I believe wchar_t allows for non-ASCII input. But what about my functions such as fgets/strcpy that do not work with wchar_t data type? I cannot find supported function replacements.
Please don't do the entire problem for me, this is an assignment for my class but general advice is greatly appreciated.
I've tried using wchar_t in place of char. I tried to use fgetsws in place of fgets but even when include the compiler doesn't recognize fgetsws as a library function. I'm running this on ubuntu linux 64 bit machine.
pa2.h================================================
#ifndef pa2_h
#define pa2_h
int shflag;
sigset_t new, old, nomask;
struct shbuff
{
char data[1024];
int size;
};
void flagfunc();
void block();
void sortstring(char input[]);
void waitchild();
void waitparent();
void parentsig(pid_t pid);
void childsig(pid_t pid);
#endif
pa2.c==========================================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>
#include "pa2.h"
int main(int argc, char* argv[])
{
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pid_t pid;
int mem;
FILE* fpinput;
FILE* fpout;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
char buff[1024]; // Do I conver this to wchar_t data type?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
key_t shkey;
void *ptr =0;
struct shbuff* shmem;
if(argc < 2)
{
printf("Input a file name including .txt!");
exit(1);
}
block(); //block sigusr1
pid=fork(); // child gets pid 0, parent is positive int
if(pid != 0) // parent process
{
fpinput= fopen(argv[1], "r"); // read from file
mem= shmget(shkey, sizeof(struct shbuff), IPC_CREAT | 0666); //size rounded up to nearest page size / 0666 required for server read/write
ptr= shmat(mem, (void *)0, 0); // Attach the shared memory
shmem= (struct shbuff *) ptr;
shmem->size= 0;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
while (fgets(buff,1023,fpinput) != NULL) //read in from file to buffer leaving room for terminating character
// Do I use fgetsws to replace this fgets?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{
pthread_mutex_lock(&mutex1);
sortstring(buff); //switch bytes in the buffer
pthread_mutex_unlock(&mutex1);
while (shmem->size != 0)
{
waitchild(); // wait for child to read from buff
}
pthread_mutex_lock(&mutex1);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
strcpy(shmem->data, buff); //replacement for strcpy?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pthread_mutex_unlock(&mutex1);
pthread_mutex_lock(&mutex1);
shmem->size= strlen(shmem->data); //set size to strlen of data
pthread_mutex_unlock(&mutex1);
childsig(pid); // signal to parent
}
while (shmem->size != 0)
{
waitchild(); // wait for child to read from buff
}
shmem->size= -1; //end of file
childsig(pid); //send signal
fclose(fpinput); //close file
shmdt(shmem); // detach from shared memory
printf("Transferred.\n\n");
} //end of else if (pid != 0)
else //if pid is 0 then process the child
{
fpout= fopen("output.txt", "w");
mem= shmget(shkey, sizeof(struct shbuff), IPC_CREAT | 0666); //size rounded up to nearest page size / 0666 required for server read/write
ptr= shmat(mem, (void *)0, 0); // attach to shared memory
shmem= (struct shbuff*) ptr; //convert the sharedMemory into struct
while (shmem->size != -1) // while not EOF
{
while (shmem->size == 0)
{
waitparent(); //wait for the child to read from shared memory
}
if (shmem->size != -1) //if not EOF
{
fputs(shmem->data,fpout); //copy the contents into the outFile
shmem->size = 0; //re-zero size after emptying data buffer
parentsig(getppid()); //parent signal
}
}
fclose(fpout); // closes output file
shmdt(shmem); // detach shared memory
kill(getpid(),SIGTERM); // Kills this process politely with sigterm rather than sigkill, We are civilized
}
exit(0);
}
void flagfunc()
{
shflag = 1;
}
void sortstring(char input[]){
char temp;
int i= 0;
for(i=0; i<strlen(input); i+=2){
temp= input[i];
input[i]= input[i+1];
input[i+1]= temp;
}
}
void block()
{
signal(SIGUSR1,flagfunc);
sigemptyset(&nomask); //empty mask
sigemptyset(&new);
sigaddset(&new, SIGUSR1); //add sigusr1 signal to mask
sigprocmask(SIG_BLOCK,&new,&old); //block new/old signals
}
void waitchild()
{
while (shflag==0)
{
sigsuspend(&nomask); //wait on child signal
}
shflag=0; //reset flag
sigprocmask(SIG_SETMASK,&old,NULL);
}
void waitparent()
{
while (shflag==0)
{
sigsuspend(&nomask); //wait for parent
}
shflag=0; //reset flag
sigprocmask(SIG_SETMASK,&old,NULL);
}
void childsig(pid_t pid)
{
kill(pid,SIGUSR1); //sends parent signal
}
void parentsig(pid_t pid)
{
kill(pid,SIGUSR1); //sends child signal
}

Fibonacci shared memory processes between two c files

Hello I have a single file in c that shares memory from the parent to child but I need my code separated into two separate files while still sharing the memory. I need the parent to create the shared memory and get the input of the fib number. Then the child process opens the share memory object to read the value n and overwrite the value n by the value of fib(n). and displays the fib series. This is what I have now
#include <stdlib.h>
#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
// So we could use other sizes without editing the source.
#ifndef MAX_SEQUENCE
# define MAX_SEQUENCE 10
#endif
// Check that MAX_SEQUENCE is large enough!
#if MAX_SEQUENCE < 2
#error MAX_SEQUENCE must be at least 2
#endif
typedef struct{
long fib_sequence[MAX_SEQUENCE];
int sequence_size;
} shared_data;
int main()
{
int a, b, m, n, i;
a = 0; b = 1;
printf("Enter the number of a Fibonacci Sequence:\n");
// Always check whether input conversion worked
if (scanf("%d", &m) != 1) {
printf("Invalid input, couldn't be converted.\n");
return EXIT_FAILURE;
}
if (m <= 0) {
printf("Please enter a positive integer\n");
return EXIT_FAILURE; // exit if input is invalid
} else if (m > MAX_SEQUENCE) {
printf("Please enter an integer less than %d\n", MAX_SEQUENCE);
return EXIT_FAILURE; // exit if input is invalid
}
/* the identifier for the shared memory segment */
int segment_id;
/* the size (in bytes) of the shared memory segment */
size_t segment_size = sizeof(shared_data);
/* allocate a shared memory segment */
segment_id = shmget(IPC_PRIVATE, segment_size, S_IRUSR | S_IWUSR);
// Check result of shmget
if (segment_id == -1) {
perror("shmget failed");
return EXIT_FAILURE;
}
/* attach the shared memory segment */
shared_data *shared_memory = shmat(segment_id, NULL, 0);
// Check whether attaching succeeded
if ((void*)shared_memory == (void*)-1) {
perror("shmat failed");
goto destroy; // clean up
}
printf("\nshared memory segment %d attached at address %p\n", segment_id, (void*)shared_memory);
shared_memory->sequence_size = m;
pid_t pid;
pid = fork();
if (pid == 0){
printf("Child is producing the Fibonacci Sequence...\n");
shared_memory->fib_sequence[0] = a;
shared_memory->fib_sequence[1] = b;
for (i = 2; i < shared_memory->sequence_size; i++){
n = a+b;
shared_memory->fib_sequence[i] = n;
a = b;
b = n;
}
printf("\nChild ends\n");
}
else{
printf("Parent is waiting for child to complete...\n");
wait(NULL);
printf("Parent ends\n");
for(i = 0; i < shared_memory->sequence_size; i++) {
printf("%ld ", shared_memory->fib_sequence[i]);
}
printf("\n");
}
/* now detach the shared memory segment */
if (shmdt(shared_memory) == -1) {
fprintf(stderr, "Unable to detach\n");
}
destroy:
/* now remove the shared memory segment */
shmctl(segment_id, IPC_RMID, NULL);
return 0;
}
There are a couple of options for shared memories :
Datapools - Datapool is an allocated location that kernel provides to a process upon request. Then other processes use the name which was used to create the data pool to connect to it and read/write from it.
Pipelines - Pipeline is another form of sharing resources which again kernel provides upon request. The difference is pipeline is usually one-way whereas data pool can be read and written by all the processes. Also, reads from the pipeline are destructive.
Files - You can also use files which is the most basic and you are probably familiar with it.
These are basic explanations, you have to research on these topics to fully understand and use them. Also, each operating system has a specific way of using these concepts, but all of them provide it (in their own way).
Instead of attaching the shared memory in the parent and then inheriting it in the client, use ftok() to get a common shared memory key that's used by both processes.
Create a file fibonacci in your current directory, this will be used in the calls to ftok().
When the parent forks the child process, it calls execl() to execute the child program, rather than including the child code directly. The child program doesn't need any of the fork() code, it just needs to attach to the same shared memory segment and fill in the results.
fibonacci.h
#ifndef FIBONACCI_H
#define FIBONACCI_H
// So we could use other sizes without editing the source.
#ifndef MAX_SEQUENCE
# define MAX_SEQUENCE 10
#endif
// Check that MAX_SEQUENCE is large enough!
#if MAX_SEQUENCE < 2
#error MAX_SEQUENCE must be at least 2
#endif
#define TOKEN_PATH "fibonacci"
typedef struct{
long fib_sequence[MAX_SEQUENCE];
int sequence_size;
} shared_data;
#endif
testparent.c
#include <stdlib.h>
#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
#include "fibonacci.h"
int main()
{
int m, i;
printf("Enter the number of a Fibonacci Sequence:\n");
// Always check whether input conversion worked
if (scanf("%d", &m) != 1) {
printf("Invalid input, couldn't be converted.\n");
return EXIT_FAILURE;
}
if (m <= 0) {
printf("Please enter a positive integer\n");
return EXIT_FAILURE; // exit if input is invalid
} else if (m > MAX_SEQUENCE) {
printf("Please enter an integer less than %d\n", MAX_SEQUENCE);
return EXIT_FAILURE; // exit if input is invalid
}
/* the identifier for the shared memory segment */
int segment_id;
/* the size (in bytes) of the shared memory segment */
size_t segment_size = sizeof(shared_data);
/* Get shared memory token */
key_t token = ftok(TOKEN_PATH, 0);
if (token == -1) {
perror("ftok");
return EXIT_FAILURE;
}
/* allocate a shared memory segment */
segment_id = shmget(token, segment_size, S_IRUSR | S_IWUSR | IPC_CREAT);
// Check result of shmget
if (segment_id == -1) {
perror("shmget failed");
return EXIT_FAILURE;
}
/* attach the shared memory segment */
shared_data *shared_memory = shmat(segment_id, NULL, 0);
// Check whether attaching succeeded
if ((void*)shared_memory == (void*)-1) {
perror("shmat failed");
goto destroy; // clean up
}
printf("\nshared memory segment %d attached at address %p\n", segment_id, (void*)shared_memory);
shared_memory->sequence_size = m;
pid_t pid;
pid = fork();
if (pid == 0){
execl("./testchild", "./testchild", (char *)NULL);
perror("execl"); // If it returns it must have failed
return EXIT_FAILURE;
}
else{
printf("Parent is waiting for child to complete...\n");
wait(NULL);
printf("Parent ends\n");
for(i = 0; i < shared_memory->sequence_size; i++) {
printf("%ld ", shared_memory->fib_sequence[i]);
}
printf("\n");
}
/* now detach the shared memory segment */
if (shmdt(shared_memory) == -1) {
fprintf(stderr, "Unable to detach\n");
}
destroy:
/* now remove the shared memory segment */
shmctl(segment_id, IPC_RMID, NULL);
return 0;
}
testchild.c
#include <stdlib.h>
#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
#include "fibonacci.h"
int main()
{
int a, b, n, i;
a = 0; b = 1;
/* the identifier for the shared memory segment */
int segment_id;
/* the size (in bytes) of the shared memory segment */
size_t segment_size = sizeof(shared_data);
/* Get shared memory token */
key_t token = ftok(TOKEN_PATH, 0);
if (token == -1) {
perror("ftok");
return EXIT_FAILURE;
}
/* allocate a shared memory segment */
segment_id = shmget(token, segment_size, S_IRUSR | S_IWUSR);
// Check result of shmget
if (segment_id == -1) {
perror("shmget failed");
return EXIT_FAILURE;
}
/* attach the shared memory segment */
shared_data *shared_memory = shmat(segment_id, NULL, 0);
// Check whether attaching succeeded
if ((void*)shared_memory == (void*)-1) {
perror("shmat failed");
return EXIT_FAILURE;
}
printf("\nshared memory segment %d attached at address %p\n", segment_id, (void*)shared_memory);
printf("Child is producing the Fibonacci Sequence...\n");
shared_memory->fib_sequence[0] = a;
shared_memory->fib_sequence[1] = b;
for (i = 2; i < shared_memory->sequence_size; i++){
n = a+b;
shared_memory->fib_sequence[i] = n;
a = b;
b = n;
}
printf("\nChild ends\n");
/* now detach the shared memory segment */
if (shmdt(shared_memory) == -1) {
fprintf(stderr, "Unable to detach\n");
}
return 0;
}

Why when I press CTRL+C the program reads zero bytes? (C-Posix)

My program has to do this:
The user has to pass N absolute pathname for files by command line. Then the i-th thread, with 0<=i<= N, has to write in the i-th file a string passed by user with scanf (or fgets). If CTRL+C is pressed, the program has to print all strings that user has passed with scanf.
When I run this and I insert a string for 1 of the N files and I press CTRL+C, in the function onPress the function read returns 0 (I think that in this case not indicates that the file pointer is in the end of file) and it prints only the string "Strings:"
Code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>
#include <signal.h>
pthread_mutex_t mutex;
int fdGlobal;
void* writer (int* arg) {
int fd_in = *(arg);
char buffer[100];
pthread_mutex_lock(&mutex);
printf("Write the string that you want to insert in the file\n");
scanf("%s", &buffer);
write(fd_in, &buffer, strlen(buffer));
write(fdGlobal, &buffer, strlen(buffer));
printf("Finished\n");
pthread_mutex_unlock(&mutex);
}
void onPress(int sig) {
char buff[100];
printf("I'm going to print all strings passed in files...\n");
int rd = read(fdGlobal, &buff, sizeof(buff));
if (rd == -1) perror("Error in the read of global file\n");
printf("I read %d bytes\n", rd);
printf("Strings: %s\n", buff);
exit(0);
}
void main (int argc, char* argv[]) {
int fds[argc-1];
pthread_t tid[argc-1];
int i, mu;
if (argc<=1) {
printf("Insert a number >=1 of pathname/s\n");
}
for ( i = 1 ; i<argc; i++) {
if (argv[i][0] != '/') {
printf("Insert a pathname\n");
}
}
signal(SIGINT, onPress);
fdGlobal = open("globalFile.txt", O_CREAT|O_RDWR, 0666);
if (fdGlobal == -1) perror("Error in the open of global file\n");
mu = pthread_mutex_init(&mutex, NULL);
if (mu < 0) perror("Error in the creation of mutex\n");
for (i=0; i<argc-1; i++) {
fds[i] = open(argv[i+1], O_CREAT|O_WRONLY, 0666);
if (fds[i] < 0 ) perror("Error in the open of the file\n");
pthread_create ( &tid[i], NULL, (void*) writer, &(fds[i]) );
}
for (i=0; i<argc-1; i++) {
pthread_join(tid[i], NULL);
}
}
Your code has numerous problems revolving around async-signal-safety, buffer sizes, and (non-)concurrency, but by far the most likely reason for the symptom you describe:
the function read returns 0
is that your belief that the file pointer is not at the end of the file is misplaced.
Indeed, read() returning 0 is a positive indicator that the file offset is currently at (or past) the end of the file. If the file was newly created then I don't see any reason to think that the offset would be anywhere else. Even when the file already exists, you need to move the file offset back to the beginning to read the data written in the current run of the program. You could do this with an appropriate call to lseek(), for example.

Shmget is returning a value of -1

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);

Program using memory segment, waits for lock to have acces to data segment(basic)

I must say i know about semaphors but i dont know how to use them yet. So the thing is I pass the controll to my data segment when the int lock gets a specific value, how could i make my code work cause at this point it freezes and I can't understand why...
s.c(server) - to be runned first
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include "st.h"
int main(){
int shmid,i;
int w =1;
struct msg* m;
shmid = shmget(1271,sizeof(struct msg), IPC_CREAT|IPC_EXCL|0600);
if(shmid == -1){
perror("~~~Shmid");
exit(1);
}
m = shmat(shmid,0,0);
printf("segment attached to structure");
do{
printf("waiting...");
sleep(1);
}while(m->lock != 1);
if(m->lock == 1)
printf("lock open!");
shmdt(m);
return 0;
}
c.c(client)
int main(int argc, char *argv[]){
if(argc != 2)
perror("~~~ ./c [file name]");
exit(1);
int shmid;
struct msg* m;
shmid = shmget(1271,0,0);
if(shmid == -1){
perror("~~~Shmid");
exit(1);
}
m = shmat(shmid,0,0);
m->f = *argv[1];
m->lock = 1;
shmdt(m);
return 0;
}
st.h
struct msg{
char f[50];
int lock;
};
The error lies at the beginning of your client's code:
int main(int argc, char *argv[]){
if(argc != 2)
perror("~~~ ./c [file name]");
exit(1);
int shmid;
...
You should have put the perror() and exit() statements inside a block of curly braces.
In your current code the exit statement is always called and your client terminates without attaching to the memory block and changing the value of the lock.
That should be:
data = shmat(shmid, (void *)0, 0); // note pointer
if (data == (char *)(-1))
perror("shmat");

Resources