0

So i'm currently trying to code in unix using shared memory and the fork() function, I have an array of 10 structs and I would like to put that array into shared memory so that it can be accessed by a client program. I was hoping someone could point me in the right direction on how to do this.

the code I currently have is:

//  Compiler Directives


//  Standard Library Inclusions
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <time.h>
//Other Inclusions

struct strProcess 
{
  int nPriority;
  int nPid;
};
//  Function Prototypes (if not included within a header file)
int frand (int nInput);
int finval (int nInput);
void fsortasc(struct strProcess pArray[],int nInput);
//  Main
int main(void)
{
// Variable Declarations
int     nShmid,i,arraySize,nRpriority,j, nInput;
key_t   nKey;
char    *ptrshm, *ptrs;
int     nSize;
pid_t   pid; 
struct  strProcess pArray[10];
struct  strProcess *Array;

Array = pArray;
// Code start

nKey = 5678;
FILE *f = fopen("logfile.txt", "w");

if (f == NULL)
{
      printf("Error opening file!\n");
      exit(1);
}

printf("please enter the amount of processes to create for this cycle between 1 and 10 \n");
scanf("%d",&nInput);
if (nInput <= 0 || nInput > 10)
{
  nInput = finval(nInput);
}
printf("%d", nInput);

nSize = sizeof(pArray) * 10;
 //create segment
if ((nShmid = shmget(nKey,nSize, IPC_CREAT | 0666)) <0)
{
      perror("shmget");
      exit(1);
}
printf("segment created \n\n");
fprintf(f, "shared memory segment created");

Array *pArray = shmat(shmid,NULL, 0);
if (Array* pArray (-1)) 
{
      perror("shmat");
      exit(1);
}
printf("segment attached \n\n");
fprintf(f, "shared memory segment attached");

for(i = 0 ; i < nInput; i++)
{
    if ((pid = fork()) < 0)
    {
      perror("fork");
      exit(1);
    }
    if (pid == 0)
    {
      Array[i].nPid = getpid();
      nRpriority = frand(nInput);
      Array[i].nPriority = nRpriority;
      printf("print job created with Pid %d and priority number %d", 
      getpid(), nRpriority);
      fprintf(f, "print job created with Pid %d and priority number %d", 
      getpid(), nRpriority);
    }
}

fprintf(f, " %d processes have been created", nInput);
fsortasc(pArray, nInput);   /*sort array into ascending order by nRpriority values*/

// Function Definitions - in alphabetical order
int finval (int nInput)
{
while(nInput <= 0 || nInput > 10)                               
{
    printf("please enter a number between 1 and 10 \n");
    scanf("%d", &nInput);                                       
} 
return nInput;                                                
}

int frand (int nInput)
{   
int nRand;
nRand = (rand() % nInput)+1;                  /*set nRand == a random number 
                                               inbetween nInput and 1*/
return nRand;                                 /*return the random number*/
}

void fsortasc(struct strProcess pArray[],int nInput)  
{
struct strProcess temp;     /*temporary storage for elements being swapped*/
int i, j;

for (i = 0; i < nInput - 1; i++)                                 
{
    for (j = 0; j < (nInput - 1-i); j++)
    {
        if (pArray[j].nPriority > pArray[j + 1].nPriority)                      /*if the current element is greater than the next element*/
        {
            temp = pArray[j];                                                   
            pArray[j] = pArray[j + 1];                                          
            pArray[j + 1] = temp;                                               
        }                                                                       
    }
}
iAnwar
  • 3
  • 1
  • 2
  • Does the code you posted represent something you have that compiles? (because as is, what you have posted does not) – ryyker Jan 03 '18 at 13:59
  • the code I have does not compile, i'm just trying to work out how to put the array in the shared memory that i create – iAnwar Jan 03 '18 at 14:53
  • See this answer _[HERE](https://stackoverflow.com/a/43923618/645128)_. It goes into sufficient detail to get you started. BTW, this is actually a very useful site for getting answers from people, but as with anything, you should know the _[rules of the road](https://stackoverflow.com/help/mcve)_ to maximize your experience here. – ryyker Jan 03 '18 at 15:15
  • Possible duplicate of [How to put a variable in a shared memory?](https://stackoverflow.com/questions/43923518/how-to-put-a-variable-in-a-shared-memory) – ryyker Jan 03 '18 at 15:17

1 Answers1

1

I have an array of 10 structs and I would like to put that array into shared memory ? It's very simple, first create array 10 struct variable and then create the shared memory using shmget of required size and then attach that shared memory with pointer and finally copy array of 10 structs into pointer attached with shmat. I added below simple code to understand your requirement.

typedef struct company {
        int emp_id;
}cmp;
int main(int argc,char *argv[]) {
        cmp cmp_info[10];
        int shm_id, sze = sizeof(cmp_info) ,i;
        /* I have an array of 10 structs -- with some data like emp_id*/
        for(i=0 ;i<10 ;i++) {
        printf("\n enter emp % Id \n",i);
        scanf("%d",&cmp_info[i].emp_id);
        }
        /* create the shared memory of 'sze' size. */
        shm_id = shmget(10,sze, IPC_CREAT | 0664);
        perror("shmget");
        /* attach the shared memory with shm_id */
        cmp *shm_ptr = shmat(shm_id, NULL, 0);
        perror("shmat");
        /* I have an array of 10 structs and I would like to put that array into shared memory  */
        shm_ptr = cmp_info;//now shared memory contains array of 10 struct data 

        /** print using shm_ptr to verify **/
        for(i=0;i<10;i++) {
        printf("Employee[%d] Id is : [%d]\n",i,shm_ptr[i].emp_id);
        }
        /* once above things are done clients program can read from shared memory */
        /** finaly de-atach the shared memory */
        shmdt(shm_ptr);
}

Below snapshot is for your code, Explanation is in comments.

struct strProcess {
        int nPriority;
        int nPid;
};
int main(int argc,char *argv[]) {
        // Variable Declarations
        int     nShmid,i,arraySize,nRpriority,j, nInput;
        key_t   nKey;
        char    *ptrshm, *ptrs;
        int     nSize;
        struct  strProcess pArray[10];//array of 10 structure
        struct  strProcess *Array;
        //Array = pArray;
        nKey = 5678;
        FILE *f = fopen("logfile.txt", "w");
        if(f == NULL) {
                printf("Error opening file!\n");
                exit(1);
        }
        nSize = sizeof(pArray);
        //create segment
        if((nShmid = shmget(nKey,nSize, IPC_CREAT | 0666)) < 0) {
                perror("shmget");
                exit(1);
        }
        else {
                perror("shmget");
                fprintf(f, "\n shared memory segment created\n");
        }
        Array  = shmat(nShmid, NULL, 0);
        perror("shmat");
        /** loop to create exaCtly 10 process */
        nInput = 10; /** call finval function **/
        for(i = 0 ; i < nInput; i++) {
                if(fork() == 0) {
                        srand(getpid());
                        Array[i].nPid = getpid();
                        nRpriority = rand()%10 + 1;//putting random no b/w 1 to 10..u can call your function also
                        Array[i].nPriority = nRpriority;
                        fprintf(f, "\nprint job created with Pid [%d] and priority number [%d]\n",
                                        Array[i].nPid, Array[i].nPriority);
                        break;//must to avoid repeating
                }
                else {
                        ;//parent does nothing
                }
        }
        shmdt(Array);
        //fprintf(f,"\n total [%d] processes have been created\n",nInput);
        /* call fsortasc(pArray, nInput); */
        fclose(f);
}

I hope it helps.

Achal
  • 11,821
  • 2
  • 15
  • 37
  • but would i not need a key to access the shared memory in the client – iAnwar Jan 04 '18 at 15:57
  • Yes created shared memory will be identified by `shmid` and `key`, you can check using `ipcs -m` command. `Key` is not required because once data is copied into pointer(`shmat` address) you can use that `pointer` to access shared memory in the client. – Achal Jan 04 '18 at 16:43
  • Thank you for the help. if I wanted to put a char into the shared memory in front of the array. How would I go about doing that? – iAnwar Jan 05 '18 at 15:54
  • Hi sorry to keep bothering you but, there was an issue with receiving the array in the client program. i tried to print it out but all I am getting is ones I was wondering if you could help – iAnwar Jan 07 '18 at 11:54
  • @iAnwar sorry is not required bro. I don't know how you are receiving array in client program so I can't guess. Can you modify your question and put that particular portion of code where you are not receiving not correctly ? – Achal Jan 07 '18 at 15:13