When I reach the line routerInfo->areaID, I got segment fault: 11 on that part.
It seem that I do not allocate the memory successfully.
I just do not know why.
Can any one solve this problem?
My header is like this:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include<memory.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <semaphore.h>
#include <time.h>
#include <signal.h>
#include <fcntl.h>
#include <stdbool.h>
#include <netdb.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#define QUEUE_SIZE 300
#define MAX_CONN 10
#define TYPE_ROUTE 1
#define TYPE_TERMINAL 2
#define CONN_INIT false
#define CONN_ESTB true
#define CSPORT 39246
struct localInfo{
char router_ID[16];
int helloTime;
int protocol_Version;
int update_Interval;
int area_ID;
int neighborNum;
};
//shared information struct
and My main function is:
#include "BasicHeader.h"
int shared_hello, shared_lsa, shared_ping, shared_data, shared_localInfo;//using shared memory
pid_t childpid;//using for child process
int main(){
printf("Starting router ... ");
sleep(1);
key_t keyForLocalInfo = ftok(".", 1);
shared_localInfo = shmget ( keyForLocalInfo , sizeof(struct localInfo) , IPC_CREAT) ;
if (shared_localInfo == -1) {perror("error creating");exit(1);}
printf("shared_localInfo: %d\n", shared_localInfo);
//creating the queue for shared_localInfo
system("ipcs -m");
//show the shm status
//creating the sharing memory finished
struct localInfo *routerInfo = (struct localInfo*) shmat (shared_localInfo, (void *)0, 0);
if (routerInfo == NULL) {
perror("shmat");exit(1);
}
routerInfo->area_ID = 0;
routerInfo->helloTime = 45;
routerInfo->neighborNum = 0;
routerInfo->protocol_Version = 1;
routerInfo->update_Interval = 180;
shmdt(routerInfo);
int err = 0;
if ((err = shmctl(shared_localInfo, IPC_RMID, 0) == -1))
perror("shmctl shared_localInfo");
}
Change the permissions on semget to allow access e.g.
shmget(keyForLocalInfo, sizeof(struct localInfo),
IPC_CREAT | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
Note that shmat returns a ptr set to -1, not NULL, and thus the error check was not catching the error. The code should have been
struct localInfo *routerInfo = (struct localInfo*) shmat (shared_localInfo, (void *)0, 0);
if (routerInfo == (void *) -1)
{
perror("shmat");
exit(1);
}
Related
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define BUFF_SIZE 1024
typedef struct {
long data_type;
int data_num;
char data_buff[BUFF_SIZE];
} t_data;
int main(){
key_t msqid;
int ndx = 0;
t_data data;
msqid = msgget( (key_t)1234, IPC_CREAT | 0666);
if ( -1 == msqid)
{
perror( "msgget() fail");
exit( 1);
}
return 0;
}
and next, i do
gcc -o parent parent.c
and next,
./parent
but the result is
msgget() fail: Function not implemented
I don't know why the msgget function is not implemented even though this is just simple code.
How can i fix my code??
Within a Ubuntu virtal machine, I have created two c programs called "server" and "client". When I run server with an input (some integer) and then run client afterwards, client will output the integer that I gave to server. This is working with shared memory. My problem is, after client receives the info, it sets a variable to "CONSUMED", and server has a loop that waits for that to happen, but it never seems to work correctly. This all works if I remove the loop altogether, but I need it in there to be able to ensure that client receives the integer and I don't just continue without it happening.
Here is my code for server.c:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include "shm.h"
int main(int argc, char* argv[]){
int retVal = 0;
ShmData *addr;
if(argc != 2){
printf("please enter 1 argument.\n");
return 0;
}
int fd = shm_open("shm.h", O_CREAT | O_RDWR , 0666);
if(fd == -1){
printf("!!!error with shm_open.\n");
}
if(ftruncate(fd, sizeof(ShmData)) == -1){
printf("!!!error with ftruncate.\n");
}
addr = mmap(0, sizeof(ShmData), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(addr == MAP_FAILED){
printf("!!!error with mmap.\n");
}
addr->status = INVALID;
addr->data = atoi(argv[1]);
addr->status = VALID;
printf("[Server]: Server data Valid... waiting for client\n");
while(addr->status != CONSUMED){
sleep(1); //THIS LOOP NEVER EXITS
}
printf("[Server]: Server Data consumed!\n");
munmap(addr, 0);
if(close(fd) == -1){
printf("!!!error with close.\n");
}
shm_unlink("smh.h");
printf("[Server]: Server exiting...\n\n\n");
return(retVal);
}
Here is my code for client.c:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include "shm.h"
int main(int argc, char* argv[]){
int retVal = 0;
int fd = shm_open("shm.h", O_CREAT | O_RDWR , 0666);
if(fd == -1){
printf("!!!error with shm_open.\n");
}
ShmData *addr;
addr = mmap(0, sizeof(ShmData), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
printf("[Client]: Waiting for valid data ...\n");
while(addr->status != VALID){
sleep(1);
}
printf("[Client]: Received %d\n", addr->data);
addr->status = CONSUMED;
munmap(addr, 0);
printf("[Client]: Client exiting...\n");
return(retVal);
}
And here is the shm.h file:
enum StatusEnum{INVALID, VALID, CONSUMED};
typedef struct{
enum StatusEnum status;
int data;
}ShmData;
I've been banging my head against the computer screen for a long time but I still don't see anything wrong with my code. How can I get this loop to succeed and exit?
I'm writing some code for a project and I have an issue when I try to update an area of shared memory with another process.
Basically one process create a shared memory, then it creates one child that, using execve, execute a process the aim of which is to update that shared memory knowing its key.
At the end the main process prints all the datas from the shm to stdout.
At that point I have noticed that shm has not been updated.
I can't understand why. I've tried with regular assignment (=) or assigning every field with a function (updatef), but it doesn't work.
(Of course in the real program I used semaphores to regulate the access to shm, i wrote this code to minimize the code to see the problem)
Process t:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#define mykey 100
#define maxname 100
#define shmsz 5
#define perms 0666
struct pdata{
pid_t ppid;
char ptype;
char pname[maxname];
unsigned long pgenome;
};
void updatef(struct pdata a, struct pdata p){
a.ppid = p.ppid;
a.ptype = p.ptype;
strcpy(a.pname, p.pname);
a.pgenome = p.pgenome;
}
int main(){
int shmid;
struct pdata *addr;
shmid = shmget(mykey, sizeof(struct pdata) * shmsz, IPC_CREAT | perms);
addr = (struct pdata*) shmat(shmid, NULL, 0);
for(int i=0; i<shmsz; i++){
addr[i].ppid = -1;
}
switch(fork()){
case 0:
{
char *args[] = {"u", NULL};
execve("u", args, NULL);
}
break;
}
sleep(2);
for(int i=0; i<shmsz; i++){
printf("%d %c %s %lu\n", addr[i].ppid, addr[i].ptype, addr[i].pname, addr[i].pgenome);
}
shmdt(addr);
shmctl(shmid, IPC_RMID, 0);
return 0;
}
Process u:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#define mykey 100
#define maxname 100
#define shmsz 5
#define perms 0666
struct pdata{
pid_t ppid;
char ptype;
char pname[maxname];
unsigned long pgenome;
};
void updatef(struct pdata a, struct pdata p){
a.ppid = p.ppid;
a.ptype = p.ptype;
strcpy(a.pname, p.pname);
a.pgenome = p.pgenome;
}
int main(){
int shmid;
struct pdata *addr;
struct pdata p;
shmid = shmget(mykey, sizeof(struct pdata) * shmsz, perms);
addr = (struct pdata*) shmat(shmid, NULL, 0);
p.ppid = getpid();
p.ptype = 'A';
strncpy(p.pname, "PIPPO", maxname);
p.pgenome = 10;
for(int i=0; i<shmsz; i++){
updatef(addr[i], p);
}
shmdt(addr);
return 0;
}
Short answer is of course passing pointer instead of value and that'll do
updatef(&arr[i], p);
Long answer lies in pass by value and pass by reference, when updatef is called with addr[i] as in
updatef(arr[i], p);
essentially the value is copied to calling function and never gets reflected to attached pointer viz addr as a result the original addr pointer get unchanged on the other hand when we pass the address like
updatef(&addr[i], p);
//or
updatef(addr+i, p);
reference is passed which inturn will update the contents pointed to by addr+i pointer
to add on IMO splitting the code will make this more presentable and readable and maintainable and bla bla bla here is a bit
File 1 - s.h, keep shared and global data here
#ifndef S_H_INCLUDED
#define S_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#define mykey 100
#define maxname 100
#define shmsz 5
#define perms 0666
struct pdata{
pid_t ppid;
char ptype;
char pname[maxname];
unsigned long pgenome; };
#endif
t.c
#include "s.h" // include global header here
int main(){
int shmid;
struct pdata *addr;
shmid = shmget(mykey, sizeof(struct pdata) * shmsz, IPC_CREAT | perms);
addr = (struct pdata*) shmat(shmid, NULL, 0);
for(int i=0; i<shmsz; i++){
addr[i].ppid = -1;
}
switch(fork()){
case 0:
{
char *args[] = {"u", NULL};
execve("u", args, NULL);
}
break;
}
sleep(2);
for(int i=0; i<shmsz; i++){
printf("%d %c %s %lu\n", addr[i].ppid, addr[i].ptype, addr[i].pname, addr[i].pgenome);
}
shmdt(addr);
shmctl(shmid, IPC_RMID, 0);
return 0;
}
u.c
#include "s.h" // common included here
static void updatef(struct pdata *a, struct pdata p){
a->ppid = p.ppid;
a->ptype = p.ptype;
strcpy(a->pname, p.pname);
a->pgenome = p.pgenome;
}
int main(){
int shmid;
struct pdata *addr;
struct pdata p;
shmid = shmget(mykey, sizeof(struct pdata) * shmsz, perms);
addr = (struct pdata*) shmat(shmid, NULL, 0);
p.ppid = getpid();
p.ptype = 'A';
strncpy(p.pname, "PIPPO", maxname);
p.pgenome = 10;
for(int i=0; i<shmsz; i++){
updatef(addr+i, p);
}
shmdt(addr);
return 0;
}
and the final build step
gcc t.c -o t
gcc u.c -o u
I created a program to test the execution of shared memory.
One process creates the shared memory and writes to it.
The other reads from it.
It works perfectly, except for printing a string.
First program:
#define mykey 12345
#define perms 0666
struct pdata{
int ppid;
char ptype;
char *pname;
unsigned long pgenome;
};
int main(int argc, char **argv){
int shmid;
char *args[] = {"test2", NULL};
struct pdata *ap;
struct pdata p0={12, 'A', "PIPPO", 100};
shmid = shmget(mykey, sizeof(struct pdata) * 1, perms | IPC_CREAT | IPC_EXCL);
ap = (struct pdata*) shmat(shmid, NULL, 0);
ap[0] = p0;
printf("%s\n", ap[0].pname);
if(execve("test2", args, NULL) == -1){
printf("Errore execve\n");
}
shmdt(ap);
shmctl(shmid, IPC_RMID, 0);
return 0;
}
Second program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <time.h>
#define mykey 12345
#define perms 0666
struct pdata{
int ppid;
char ptype;
char *pname;
unsigned long pgenome;
};
int main(){
int shmid = shmget(mykey, sizeof(struct pdata) * 1, perms);
struct pdata *ap;
ap = (struct pdata*) shmat(shmid, NULL, 0);
printf(
"ap[0].ppid=%d\nap[0].ptype=%c\nap[0].pname=%s\nap[0].pgenome=%lu\n",
ap[0].ppid,
ap[0].ptype,
ap[0].pname,
ap[0].pgenome
);
shmdt(ap);
shmctl(shmid, IPC_RMID, 0);
return 0;
}
It doesn't make sense to put a pointer in shared memory. The receiving process now knows the address of the string in the other process' memory space, but that doesn't do it any good. Instead, put the string itself in shared memory.
For example, change:
char *pname;
to:
char pname[512];
And adjust the rest of your program appropriately.
Can I use the kill() function to send a signal to another process? It should be possible, but kill() fails and I can't understand why.
I have two programs (process_1 and process_2). The first one should set a signal handler to increase a variable, than create a child that uses execve and loads process_2. The other program should send the signal using kill(). I used the shared memory to share process_1's pid through a struct (because I have other variables to share). The code of the first program is as follows:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/wait.h>
#define KEY_SM 1234
static int value_to_change=0;
typedef struct keys{
pid_t pid_process;
}keynote;
static void test_handler(int signo){
if(signo=SIGUSR1){
printf("received SIGUSR1\n");
value_to_change++;
}
}
int main(){
if((signal(SIGUSR1, test_handler))==SIG_ERR) perror("Errore allocazione SIGUSR1");
int flags = S_IRUSR|S_IWUSR|IPC_CREAT;
size_t shm_size = sizeof(keynote);
int shm_id = shmget(KEY_MC, shm_size, flags);
keynote *chv = shmat(shm_id, NULL, 0);
chv->pid_process=getpid();
printf("%d\n",chv->pid_process);
int process_2;
process_2=fork();
if(process_2==0){
char* argv[]={"process_1", "process_2", NULL};
if((execve("process_2", argv, NULL))<0) perror("execve error");
exit(0);
}else if(process_2<0)perror("fork error");
return 0;
}
The second program code is:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/wait.h>
#define KEY_SM 1234
typedef struct keys{
pid_t pid_process;
}keynote;
static void signal_to_send(pid_t process){
int ret=kill(process, SIGUSR1);
printf("%d", ret);
}
}
int main(int argc, char **argv){
int pid_of_process_1;
int flags = S_IRUSR|S_IWUSR|IPC_CREAT;
size_t shm_size = sizeof(keynote);
int shm_id = shmget(KEY_MC, shm_size, flags);
keynote *chv = shmat(shm_id, NULL, 0);
signal_to_send(chv->pid_process);
return 0;
}
process_1 does not wait for process_2. It just exits immediately. At which point process_2 may not even have started. So when process_2 sends the signal, process_1 is likely to not exist anymore.
– kaylum