Shmget: Invalid argument. Why i get this error? - c

I get a "shmget: Invalid argument error" while i try to execute this part of code
int *nFS, *spb, *cell1, shmid;
key_t key = 5768;
//i need a shared memory segment in which i can put 3 ints
if ((shmid = shmget(key, (sizeof(int) * 3), IPC_CREAT | 0666)) < 0 ) {
perror("shmget");
exit(1);
}
if ((spb = (int)shmat(shmid, NULL, 0))== -1 ){
perror("shmat");
exit(1);
}
cell1= spb + 1 ;
nFS= cell1 + 1;
//i try to assign here 7 to nFS
*nFS=7;
there is something wrong here but i can't figure out what. Can you help me?
Thanks, Alex.

From the shmget(1) man page:
EINVAL A new segment was to be created and size < SHMMIN or size >
SHMMAX, or no new segment was to be
created, a segment with given key existed, but size is greater than the size of that segment.
You should check whether you still have an segment for this key using ipcs and remove it with ipcrm.

In my case, the value of the size_t __size parameter was less than 0.
For reference, shmget() is prototyped as:
int shmget(key_t __key, size_t __size, int __shmflg)

Related

Shared memory on C struct not working correctly

I'm working on a small program that simulates a puzzle game, where I can print the state of the board, or move up, down, left, or right but am having an issue when I tried implementing it with shared memory. I have a struct in a header file that has a char *[4][4]
that is used in both the the other files
The setup is like this
// Instance of Board for the current state of the game.
Obj obj; // is initialized but not here for sake of space and post size
struct obj *pobj;
int main()
{
key_t key = ftok("/afs/x/y/z", 'b');
//Make shared memory
size_t BLOCK_SIZE = sizeof(struct Board);
int shmid = shmget(key, BLOCK_SIZE, 0666 | IPC_CREAT);
if (shmid == -1)
{
fail("Cannot create shared memory");
}
pobj = (Obj *) shmat(shmid, 0, 0);
if (pobj == (struct Board *) -1)
{
fail("Can't map shared memory segment into address space");
}obj
// setting pobj values to obj values
for(int i = 0; i < OBJ_ROWS; i++){
for(int j = 0; j < OBJ_COLS; j++){
pobj->field[i][j] = obj.field[i][j];
}
}
//Loop through and print the values just put in, I get the correct values I put in
shmdt( pobj );
return 0;
}
I get the correct values I put in
but when I access via this
key_t key = ftok("/afs/x/y/z", 'b');
//Make shared memory
int shmid = shmget( key, BLOCK_SIZE, 0666 | IPC_CREAT );//this IPC_CREAT not needed
if( shmid == -1){
fail( "Cannot create shared memory" );
}
pobj= (OBJ *) shmat(shmid, 0, 0);
if(pobj == (struct Obj *) -1){
fail( "Cannot map shared memory segment into address space" );
}
// loop through and print out values
I get nothing but garbage values like
# # ▒▒▒▒▒&▒E▒x▒▒U܋u܋E▒щ▒▒▒w▒▒▒▒
▒E▒▒}▒~▒▒E▒▒}▒~▒▒ ▒▒&▒E▒x▒▒U܋u܋E▒щ▒▒▒w▒▒▒▒
▒E▒▒}▒~▒▒E▒▒}▒~▒▒
▒E▒x▒▒U܋u܋E▒щ▒▒▒w▒▒▒▒
▒E▒▒}▒~▒▒E▒▒}▒~▒▒ ▒x▒▒U܋u܋E▒щ▒▒▒w▒▒▒▒
▒E▒▒}▒~▒▒E▒▒}▒~▒▒ ▒U܋u܋E▒щ▒▒▒w▒▒▒▒
▒E▒▒}▒~▒▒E▒▒}▒~▒▒ ▒u܋E▒щ▒▒▒w▒▒▒▒
▒E▒▒}▒~▒▒E▒▒}▒~▒▒
What is causing the difference in these values?
Edit: Fixed the issue by removing the IPC_CREAT from the second file that was causing issues and changed array to int[4][4];
You created a brand new shared memory block in both programs. You want to create memory in reset.c, and read it in fifteen.c. Remove the IPC_CREAT in fifteen.c. You can learn more here, where the syscall specifies:
IPC_CREAT
Create a new segment. If this flag is not used, then
shmget() will find the segment associated with key and
check to see if the user has permission to access the
segment.
There's also something that doesn't make much sense. String literals are arrays, i.e. pointers, and you made Board just a bunch of pointers. The only data you shared in your shared memory object were the pointers, which isn't helpful for fifteen.c, fifteen.c needs to see the actual character data. Instead, fifteen.c sees a bunch of pointers that point to string literals in reset.c. This isn't particularly useful, what should fifteen.c do with a bunch of random addresses? fifteen.c wants to see actual letters - likely null terminated arrays. You'll have to make your Board object contain a 2D array of character arrays (Of definite length, say, 16). Then, you can share the character data back and forth in your file.

C linux shmget Invalid argument

int shmCreate(int id, int size)
{
int shmid
key_t key;
if ((key = ftok(".", id)) == -1) {
perror("ftok");
exit(1);
}
if ((shmid = shmget(key, size, IPC_CREAT | 0666)) == -1) {
perror("shmget");
exit(1);
}
return shmid;
}
I'm trying to write function which use shmget, where function gets size as parameter. I'm getting Invalid argument error all the time, except for size = 1. When I pass size other than 1 i got error, but the memory segment is created when i check ipcs -m, and it has size of 1. How do I get rid of this error?
According to the man page for shmget(2):
EINVAL A segment for the given key exists, but size is greater than
the size of that segment.
You cannot attach a segment that already exists with a larger size. So you need to remove it first or use a different key.

shmctl throws "cannot allocate memory" in C

I have this code:
#define SHMSIZE 8388606
int main()
{
int shmid;
void *shmPtr;
char *shm;
if ((shmid = shmget(IPC_PRIVATE, sizeof(char) * SHMSIZE , IPC_CREAT | 0666)) < 0) {
perror("shmget");
exit(1);
}
if ((shmPtr = shmat(shmid, NULL, 0)) == (char *) -1) {
perror("shmat");
exit(1);
}
shm = (char *)shmPtr;
strncpy(shm, "0\n", 2);
struct shmid_ds shmid_ds;
int rtrn = shmctl(shmid, SHM_LOCK, &shmid_ds);
if(rtrn < 0) {
perror("shmctl");
exit(1);
}
else {
printf("Nailed it\n" );
}
return 0;
}
Running it, I get the error:
shmctl: Cannot allocate memory
Defining smaller value for SHMSIZE fixes the error, but what I found weird is that this error is thrown in the "shmctl" part. My reasoning tells me that this error is supposed to be thrown in the "shmget" part.
How does this code runs successfully through the shmget() call? Did I miss something important?
Read this, It may help you to solve your problem:
The caller can prevent or allow swapping of a shared memory segment
with the following cmd values:
SHM_LOCK (Linux-specific)
Prevent swapping of the shared memory segment. The caller
must fault in any pages that are required to be present
after locking is enabled. If a segment has been locked,
then the (nonstandard) SHM_LOCKED flag of the shm_perm.mode
field in the associated data structure retrieved by
IPC_STAT will be set.
SHM_UNLOCK (Linux-specific)
Unlock the segment, allowing it to be swapped out.
In kernels before 2.6.10, only a privileged process could employ
SHM_LOCK and SHM_UNLOCK. Since kernel 2.6.10, an unprivileged
process can employ these operations if its effective UID matches the
owner or creator UID of the segment, and (for SHM_LOCK) the amount of
memory to be locked falls within the RLIMIT_MEMLOCK resource limit
(see setrlimit(2)).
Try this:
int rtrn = shmctl(shmid, IPC_STAT, &shmid_ds);

Shared Memory in C: Shmget Issues

int shmid;
int* locat;
//create shared memory segment
shmid = shmget(6666, size, 0666);
if (shmid < 0) {
perror("shmget");
exit(1);
}
locat = (int *) shmat(shmid, NULL, 0);
if (locat == (int *) -1) {
perror("shmat");
exit(1);
}
I am setting up shared memory as such, yet I keep getting this error: shmget: No such file or directory
This code was working fine, not sure why this occurs now.
As the man says
IPC_CREAT
Create a new segment. If this flag is not used, then shmget() will find the segment associated with key and check to see if the user has permission to access the segment.
You have to add IPC_CREAT to your shmget call
shmid = shmget(6666, size, IPC_CREAT | 0666);
You could also use the IPC_EXCL to ensure that the segment is newly created
IPC_EXCL
This flag is used with IPC_CREAT to ensure that this call
creates the segment. If the segment already exists, the
call fails.
There are two things :
When you want to initialize a shared memory ( corresponding to a particular key value ) , you have to BITWISE OR the permission number with IPC_CREAT.
Just like
shmget(6666 , size , 0666|IPC_CREAT);
When you want to attach the same segment ( identified by the key value ) to another process , IPC_CREAT is not mandatory as the shared memory has already been created the the logical address space.

Shared Memory Code Snippet in C

I came across the following code snippet
int seg1 = shmget( number, 1, 0660 );
if( -1 != seg1 )
{
struct shmid_ds buf;
shmctl( seg1, IPC_RMID, &buf );
fprintf( stderr, "Removed existing shared memory segment" );
}
int seg = shmget( number, 2 * size, IPC_CREAT | 0660 );
Buffer = (char*) shmat( seg, NULL, 0 );
Questions:
1) shmget( number, 1, 0660 )
f IPC_CREAT or IPC_EXCL is not specified and only 0660 is specified, what's the default IPC_ ? The does not explain this/
2) Why would one want to do a shmget for a key number with a size of 1 byte, then do a IPC_RMID and then again do a shmget of the same key with the bigger space ?
1) shmget( number, 1, 0660 ) f IPC_CREAT or IPC_EXCL is not specified and only 0660 is specified, what's the default IPC_ ? The does not explain this/
By default, neither option applies. The segment is only opened if it already exists.
2) Why would one want to do a shmget for a key number with a size of 1 byte, then do a IPC_RMID and then again do a shmget of the same key with the bigger space ?
The purpose is just to remove an existing shared memory segment regardless of its size. The shmget function will fail if size is bigger than the size of the existing segment, so using one ensures it doesn't fail.

Resources