user7222892
user7222892

Reputation: 1

No such file or directory error in shmget

I had implemented shared memory concept in C on Ubuntu . I have created two file server.c and client.c , first I have compiled server.c then compiled client.c and run it. But it showed an error. "No such file or directory" This error came in client.c file because the requested shared memory segment is not found. Kindly help me how can I solve this problem.

Here is my code

server.c

  #include<sys/types.h>
  #include<sys/shm.h>
  #include<sys/ipc.h>
  #include<string.h>
  #include<stdlib.h>
  #include<stdio.h>
  #include<errno.h>

  #define SHMSIZE 100

 int main()
 {

 int shmid;
 key_t key;
 char *shm, *s;

 key=9876;
 shmid=shmget(key,SHMSIZE,IPC_CREAT|0666);
 if(shmid<0)
 {
 printf("%s",strerror(errno));
 perror("Error in Shared Memory get statement");
 exit(1);
 }

 shm=shmat(shmid,NULL,0);
 if(shm== (char *) -1)
 {
 perror("Error in Shared Memory attachment");
 exit(1);
 }

 memcpy(shm,"Hello World",11);
 s=shm;
 s+=11;

 while(*shm!='*')
 {
 sleep(1);
 }

 return 0;
 }

client.c

#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>

#define SHMSIZE 100

int main()
{

 int shmid;
 key_t key;
 char *shm, *s;

 key=9876;
 shmid=shmget(key,SHMSIZE,0666);
 if(shmid<0)
 {
 printf("%s",strerror(errno));
 perror("Error in Shared Memory get statement");
 exit(1);
 }

 shm=shmat(shmid,NULL,0);
 if(shm== (char *) -1)
 {
 printf("%s",strerror(errno));
 perror("Error in Shared Memory attachment");
 exit(1);
 }

 for(s=shm; *s!=0;s++)
 {
 printf("%c",*s);
 }
 printf("\n");
 *shm='*';
 return 0;
 }

Upvotes: 0

Views: 12943

Answers (2)

pcdummy
pcdummy

Reputation: 133

I've been working on debugging a Frankenstein Linux Server, while doing so I copied some code from php-7.4.22 opcache to have the same behavior.

This code allocates in my case 4 Segments with 32MiB to a total of 128MiB.

/*
   +----------------------------------------------------------------------+
   | Zend OPcache                                                         |
   +----------------------------------------------------------------------+
   | Copyright (c) The PHP Group                                          |
   +----------------------------------------------------------------------+
   | This source file is subject to version 3.01 of the PHP license,      |
   | that is bundled with this package in the file LICENSE, and is        |
   | available through the world-wide-web at the following url:           |
   | http://www.php.net/license/3_01.txt                                  |
   | If you did not receive a copy of the PHP license and are unable to   |
   | obtain it through the world-wide-web, please send a note to          |
   | [email protected] so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Authors: Andi Gutmans <[email protected]>                                 |
   |          Zeev Suraski <[email protected]>                                 |
   |          Stanislav Malyshev <[email protected]>                          |
   |          Dmitry Stogov <[email protected]>                              |
   +----------------------------------------------------------------------+
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

#ifndef MIN
#define MIN(x, y) ((x) > (y) ? (y) : (x))
#endif

#define REQUEST_SIZE 128 * 1024 * 1024;

#define SEG_ALLOC_SIZE_MAX 32 * 1024 * 1024
#define SEG_ALLOC_SIZE_MIN 2 * 1024 * 1024

typedef struct
{
    size_t size;
    size_t pos; /* position for simple stack allocator */
    void *p;
} zend_shared_segment;

typedef struct
{
    zend_shared_segment common;
    int shm_id;
} zend_shared_segment_shm;

int main()
{
    key_t key = 9876;
    size_t requested_size = REQUEST_SIZE;

    int i;
    size_t allocate_size = 0, remaining_bytes = requested_size, seg_allocate_size;
    int first_segment_id = -1;
    key_t first_segment_key = -1;
    int shmget_flags;
    struct shmid_ds sds;
    zend_shared_segment_shm *shared_segments;
    zend_shared_segment_shm *shared_segments_p;
    int shared_segments_count = 0;

    printf("request_size: %d\n", requested_size);

    seg_allocate_size = SEG_ALLOC_SIZE_MAX;
    /* determine segment size we _really_ need:
     * no more than to include requested_size
     */
    while (requested_size * 2 <= seg_allocate_size && seg_allocate_size > SEG_ALLOC_SIZE_MIN)
    {
        seg_allocate_size >>= 1;
    }

    shmget_flags = IPC_CREAT | SHM_R | SHM_W | IPC_EXCL;

    /* try allocating this much, if not - try shrinking */
    while (seg_allocate_size >= SEG_ALLOC_SIZE_MIN)
    {
        allocate_size = MIN(requested_size, seg_allocate_size);
        first_segment_id = shmget(first_segment_key, allocate_size, shmget_flags);
        if (first_segment_id != -1)
        {
            break;
        }
        seg_allocate_size >>= 1; /* shrink the allocated block */
    }

    printf("seg_allocate_size: %d\n", seg_allocate_size);

    if (first_segment_id == -1)
    {
        perror("Failed to allocate first segment");
        return 1;
    }

    shared_segments_count = ((requested_size - 1) / seg_allocate_size) + 1;
    printf("shared_segments_count: %d\n", shared_segments_count);

    shared_segments_p = calloc(shared_segments_count, sizeof(zend_shared_segment_shm) + sizeof(void *) * (shared_segments_count));
    if (!shared_segments_p)
    {
        perror("Failure in calloc");
        return 1;
    }
    shared_segments = (zend_shared_segment_shm *)((char *)(shared_segments_p) + sizeof(void *) * (shared_segments_count));

    remaining_bytes = requested_size;
    for (i = 0; i < shared_segments_count; i++)
    {
        allocate_size = MIN(remaining_bytes, seg_allocate_size);
        if (i != 0)
        {
            shared_segments[i].shm_id = shmget(IPC_PRIVATE, allocate_size, shmget_flags);
        }
        else
        {
            shared_segments[i].shm_id = first_segment_id;
        }

        if (shared_segments[i].shm_id == -1)
        {
            perror("Failed to allocate additional segments");
            return 1;
        }

        shared_segments[i].common.p = shmat(shared_segments[i].shm_id, NULL, 0);
        if (shared_segments[i].common.p == (void *)-1)
        {
            perror("Failed to shmat");
            shmctl(shared_segments[i].shm_id, IPC_RMID, &sds);
            return 1;
        }
        shmctl(shared_segments[i].shm_id, IPC_RMID, &sds);

        shared_segments[i].common.pos = 0;
        shared_segments[i].common.size = allocate_size;
        remaining_bytes -= allocate_size;
    }

    printf("Shmget() successful %d\n", first_segment_id);
    return 0;
}

Run it with: gcc -o shm shm.c; sudo ./shm

Upvotes: 0

Sumit Gemini
Sumit Gemini

Reputation: 1836

The fact that shmget() fail with the "No such file or directory" means only that it hasn't found a segment with that key (being now pedantic: not id - with id we usually refer to the value return by shmget(), used subsequently) - have you checked that the shmid is the same? Your code works fine on my system.

Just added a main() around it. Hope it helps you.

 key=9876;
 shmid=shmget(key,SHMSIZE,0666);
 if(shmid<0)
 {
        printf("%s",strerror(errno));
        perror("Error in Shared Memory get statement");
        shmid = shmget(key, SHMSIZE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH | IPC_CREAT);
        if (shmid == -1)  {
                printf("%s",strerror(errno));
                perror("Error in Shared Memory get statement");
                exit(1);
        }
 }
printf("Shmget() successful %d\n",shmid);

Upvotes: 2

Related Questions