It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
The following code always returns -1 for creating shared memory. I don't know the reason for it. As far as I know my code is correct. Perror returns not such file or directory. I don't know what it is pointing to, but this file and the header are in the same directory. Here is the code:
#include "MyShared.h"
int main()
{
struct MyShared *obj;
int shmid,i,childpid;
shmid=shmget(MySharedKey,sizeof(struct MyShared),PERM);
if(shmid==-1)
printf("Failed to create shared mem\n");
obj=(struct MyShared*)shmat(shmid,NULL,0);
obj->ReadFromBuf=0;
....
}
Here is the header file. My Shared.h
#ifndef MYSHARED_H_INCLUDED
#define MYSHARED_H_INCLUDED
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PERM (S_IRWXU | S_IRGRP)
#define MySharedKey 564732
#define SIZE 512 // 512 bytes
struct MyShared
{
char buf[SIZE];
int ReadFromBuf,WriteToBuf,readbytes;
};
#endif
Why can't this code create a shared memory?
I am using ubuntu 10.04.
I am following Unix System programming by Stevens and it doesn't say anything or creation permissions for a shared memory.
Regards
Instead of
printf("Failed to create shared mem\n");
better use
perror("Failed to create shared mem");
This evaluates the errno variable and prints a more useful error message, in your case something like
Failed to create shared mem: No such file or directory
The reason is that you try to attach to a non-existing memory segment.
In order to create a shared memory segment, you need to pass the IPC_CREAT flag to shmget():
shmid=shmget(MySharedKey,sizeof(struct MyShared),PERM | IPC_CREAT);
See also http://www.kernel.org/doc/man-pages/online/pages/man2/shmget.2.html
If you are not passing this flag, it is assumed that the shared memory segment already exists and that your process wants to attach to it. This is what needs to be done by your slave processes which want to access the shared memory segment, once it has been created by some master process.
first, you lose some head file.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
second, the first argument of shmget() function is a key_t type.So you must use fotk() function to generator key.
Example:
Myshared.h
#ifndef _MYSHARED_H
#define _MYSHARED_H
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define FLAG (IPC_CREATE | IPC_EXCL)
#define SIZE 512
typedef struct {
char buf[SIZE];
int read_from_buffer, write_to_buffer, read_bytes;
} Shared;
#endif
Myshared.c
#include "Myshared.h"
#include <stdio.h>
int main(int argc, char **argv)
{
key_t key;
int shmid;
key = ftok("/dev/null", 0); # /dev/null just a example
shmid = shmget(key, sizeof(struct Shared), FLAG);
if (shmid == -1) {
perror("Create Shared Memory Error:");
}
......
}
the end, you can type man ftok and man shmget to help yourself.
Related
I'm doing an assignment for class in which we need to create some shared memory that can be accessed from 2 different programs. There is a header file called shm.h that has the kinds of data we need to be able to share. So far my code looks like this.
shm.h
#ifndef SHM_H
#define SHM_H
//<Define an enum called StatusEnus with the enumerations "INVALID", "VALID"
and "CONSUMED">
#define enum StatusEnus{INVALID, VALID, CONSUMED} StatusEnus
//<Define a typedef structure with the enum above and an "int" variable
//called "data">
#define struct ShmData{StatusEnus status; int data;}ShmData;
#define SIZE 8
#endif
server_template
#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[])
{
//void* memPtr;
int retVal = 0;
//<Confirm argc is 2 and if not print a usage string.>
if(argc != 2){
printf("Please enter 2 arguments5");
}
/*<Use the POSIX "shm_open" API to open file descriptor with
"O_CREAT | O_RDWR" options and the "0666" permissions> */
//returns -1 on error
int file = shm_open("sharedMem", O_CREAT | O_RDWR, 0666);
if (file == -1) retVal =-1;
/*<Use the "ftruncate" API to set the size to the size of your
structure shm.h>*/
retVal = ftruncate(file,SIZE);
//<Use the "mmap" API to memory map the file descriptor>
void* data = mmap(0, SIZE,PROT_WRITE | PROT_WRITE, MAP_SHARED, file, 0);
/*<Set the "status" field to INVALID>
<Set the "data" field to atoi(argv[1])>
<Set the "status" field to VALID>*/
ShmData->status = INVALID;
ShmData->data = atoi(argv[1]);
ShmData->status = VALID;
printf("[Server]: Server data Valid... waiting for client\n");
while(ShmData->status != CONSUMED)
{
sleep(1);
}
printf("[Server]: Server Data consumed!\n");
/*<use the "munmap" API to unmap the pointer>
<use the "close" API to close the file Descriptor>
<use the "shm_unlink" API to revert the shm_open call above>*/
printf("[Server]: Server exiting...\n");
return(retVal);
}
So my goal is to be able to access the fields like ShmData->StatusEnus from the server but also then be able to access these files from a separate program. However as it stands I keep getting to errors either related to the deceleration of ShmData. How do I make sure that the shared memory I am creating contains that enum and int field from my structure?
I am trying to open a shared memory segment in my main process. My terminology may be incorrect in the question but this is what I am trying to achieve:
I collect information from 7 sensors and from that I evaluate the state. I made a structure senStruct. I want to share the 7 sensor and state information to other processes with use of shared memory. In code I am opening the senfile, mapping the senStruct into it. Now I simply want to store something into state and it gives me an error.
Here is the code:
#include <fcntl.h> /* Defines O_* constants */
#include <sys/stat.h> /* Defines mode constants */
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
typedef struct senStruct {
int sensor[7];
int state;
}senStruct;
int main()
{
int fd;
size_t size = sizeof(senStruct);
senStruct *p;
fd = shm_open( "senfile" , O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR );
ftruncate (fd, size);
printf("Before mapping...p points to %p\n",p);
p =(senStruct *) mmap (NULL , size, PROT_READ | PROT_WRITE,MAP_SHARED , fd, 0);
printf("After mapping...p points to %p\n",p);
p->state=1;
return 0;
}
Output is:
Before mapping...p points to (nil)
After mapping...p points to 0xffffffffffffffff
Segmentation fault (core dumped)
Address of p after p seems doubtful to me. Looking into gdb indicates segmentation fault at p->state = 1. Is my procedure incorrect or did I miss anything?
when trying to do shmat i get allocation error, telling me i cannot accsess the memory, it did not happen to me before and i really dont know what to do.
this is the error :
0xffffffffffffffff error: Cannot access memory at address 0xffffffffffffffff
and the wiered thing is that vecBoard is allocated in the process mapped area and only get crazy when shmat is triggered. thank you all!
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/fcntl.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#define SHM_SIZE 4096
#define FLAGS IPC_CREAT
#define COLUMNS 8
#define ROWS 8
key_t key;
int main()
{
char* vecBoard;
// Creating shared memory :
if ((key = ftok("ex31.c",'k')) == -1)
{
perror("ftok");
exit(1);
}
int shm_id;
shm_id=shmget(key,SHM_SIZE,FLAGS);
if(shm_id==-1)
{
printf("error creating shared memory\n");
exit(0);
}
printf("the shared memory segment ID is: %d\n",shm_id);
vecBoard = (char *)shmat(shm_id,0,0);
if((vecBoard = (char *)shmat(shm_id,0,0)) == (char*)-1)
{
printf("error in attaching to the shared memory\n");
exit(0);
}
}
The shown code calls shmat() twice, for the same memory segment.
That's obviously wrong.
Looking at errno would help diagnose the problem (i.e. call perror on failure instead of just printf). The OS gives you information when a system call fails; don't ignore it!
If you carefully read the man page for shmget, the third argument (flags) is supposed to contain, in its low 9 bits, the permissions desired for the shared memory segment. If you just pass IPC_CREAT here, those bits are cleared to 0, so you create a segment for which nobody has either read or write permissions. Thus shmat fails (with EACCES because you are (implicitly) asking to both read and write that segment, and you don't have permission to do either.
You probably want to change it to something like IPC_CREAT | 0600, if you want the current user to be able to access the segment.
Note that before testing this again, you'll probably have to remove the existing shared memory segment with the erroneous permissions. Use the ipcs and ipcrm tools for this.
Have a problem.
I have a file which contents look like number:error_description.
Now i need to put this file to shared memory (POSIX). If any contents are modified it should be saved to the base-file.
There is a need to search in the content in the shared memory (results will be sent to a client over a message queue).
How do I implement all this? First I thought I have to open (fopen("my_file", "r")) and then I have to create shared memory and mmap the file.
Can someone help me?
edit:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <semaphore.h>
/*
* \ /tmp/errors -> Error File
*/
#define MSGQ_HANDLER "/error_handler"
#define PATH_TO_FILE "/tmp/errors"
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
int main(void) {
int fd = open(PATH_TO_FILE, O_RDWR);
struct stat file_stat;
fstat(fd, &file_stat);
printf("File size: %zd\n", file_stat.st_size);
char *byte_ptr = mmap(NULL, file_stat.st_size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if(byte_ptr == MAP_FAILED){
perror("error:");
}
while(1){
printf("%s\n", byte_ptr);
if(byte_ptr)
exit(1);
}
return EXIT_SUCCESS;
}
So far it is what I have now.
Read a line works.
How do I change the content?
Don't use fopen and forget about shared memory (the sh* API I mean). mmap is all that's needed.
Open your file with open and the right options (read/write). Then use mmap with the option MAP_SHARED. All changes in the file will be reflected directly and visible to all processes that map the same file. On Linux and Solaris (on other systems I don't know, but it is not guaranteed by POSIX or any standard) you can even access the file concurrently with read/write. It is a bad idea though.
Concurrent memory accesses from different processes will, of course, need synchronisation (mutex, semaphores etc.).
I am trying to implement shared memory on embedded device with uClinux.
My C source
#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <errno.h>
//using namespace std;
int main() {
int segment_id;
segment_id = shmget(04, getpagesize(), IPC_CREAT | 0666);
printf("Page size - %d\n",getpagesize());
printf("Error in socket - %d\n",errno);
}
I get an error
Page size - 4096
Error in socket - 38
Can anyone help me?
Thanks.
You need to test segment_id value, and use errno only if segment_id == -1.
Your key 04 looks completely bogus. You should obtain a key_t with ftok, I guess.
Also, if you have the choice, it might be better to choose the shm_open / mmap facilities for such a task.
And since I am at it, use perror to print errors, and also please remove C++ from your question title, has nothing to do with C++.
The errno 38 corresponds to ENOSYS which means function not implemented.
I missed a kernel config. I have to enable CONFIG_SYSVIPC.