问题
I have created a data structure in my C program as follows,
typedef struct {
int *array;
size_t used;
size_t size;
} Array;
void initArray(Array *a, size_t initialSize) {
a->array = (int *)malloc(initialSize * sizeof(int));
a->used = 0;
a->size = initialSize;
}
void insertArray(Array *a, int element) {
if (a->used == a->size) {
a->size *= 2;
a->array = (int *)realloc(a->array, a->size * sizeof(int));
}
a->array[a->used++] = element;
}
void freeArray(Array *a) {
free(a->array);
a->array = NULL;
a->used = a->size = 0;
}
Then I'm adding some data to that data structure from an external text file using following method,
Array read_ints (const char* file_name)
{
Array numbers;
initArray(&numbers,5);
FILE* file = fopen (file_name, "r");
int i = 0;
int count = 0;
fscanf (file, "%d,", &i);
insertArray(&numbers,i);
while (!feof (file))
{
//printf ("%d ", i);
fscanf (file, "%d,", &i);
insertArray(&numbers,i);
}
fclose (file);
return numbers;
}
Now what I need to do is, I need to make the 'Array' data structure a shared memory portion so that the both child and parent processes on my program could access that data structure. I have no idea on how to make it a shared memory. I'm aware that the shmget()
system call can be used to get a shared memory in UNIX environment. But i cannot see how to use that system call on this scenario. Please help me.
回答1:
Main code — shm-master.c
#include "posixver.h"
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <unistd.h>
#include "so-stderr.h"
enum { DEFAULT_SHM_SIZE = 65536 };
enum { DEFAULT_FTOK_ID = 0 };
static const char default_filename[] = "/etc/passwd";
static const char usestr[] = "[-adx][-f file][-s size][-i id]";
static const char optstr[] = "adf:s:x";
int main(int argc, char **argv)
{
int aflag = 0;
int xflag = 0;
int dflag = 0;
int id = DEFAULT_FTOK_ID;
size_t size = DEFAULT_SHM_SIZE;
const char *file = default_filename;
int opt;
err_setarg0(argv[0]);
while ((opt = getopt(argc, argv, optstr)) != -1)
{
switch (opt)
{
case 'a':
aflag = 1;
break;
case 'd':
dflag = 1;
break;
case 'f':
file = optarg;
break;
case 'i':
id = atoi(optarg);
break;
case 's':
size = strtoull(optarg, 0, 0);
if (size == 0)
err_error("Invalid size (%s) evaluates to zero\n", optarg);
break;
case 'x':
xflag = 1;
break;
default:
err_usage(usestr);
}
}
if (aflag + dflag + xflag > 1)
err_error("%d of 3 mutually exclusive options -a, -d and -x specified\n", aflag + dflag + xflag);
printf("ID: %d, File: %s\n", id, file);
key_t key = ftok(file, id);
printf("Key: 0x%.8" PRIX64 "\n", (uint64_t)key);
int shmflg = S_IRUSR | S_IWUSR;
if (!aflag && !dflag)
shmflg |= IPC_CREAT;
if (xflag)
shmflg |= IPC_EXCL;
int shmid = shmget(key, size, shmflg);
if (shmid < 0)
err_syserr("Failed to get shared memory ID: ");
printf("ShmID: %d\n", shmid);
if (dflag)
{
struct shmid_ds buf;
int rc = shmctl(shmid, IPC_RMID, &buf);
if (rc < 0)
err_syserr("Failed to delete shared memory: ");
printf("Shared memory removed\n");
}
else
{
void *space = shmat(shmid, 0, 0);
if (space == (void *)-1)
err_syserr("Failed to attach to shared memory: ");
printf("Shared memory allocated at 0x%" PRIXPTR "\n", (uintptr_t)space);
memset(space, '\0', size);
int rc = shmdt(space);
if (rc != 0)
err_syserr("Failed to detach from shared memory: ");
printf("Detached from shared memory\n");
}
return 0;
}
Library code — so-stderr.h
#ifndef SO_STDERR_H_INCLUDED
#define SO_STDERR_H_INCLUDED
extern void err_setarg0(const char *arg0);
extern void err_error(const char *fmt, ...);
extern void err_syserr(const char *fmt, ...);
#endif /* SO_STDERR_H_INCLUDED */
Library code — so-stderr.c
#include "so-stderr.h"
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const char *argv0 = "**undefined**";
void err_setarg0(const char *arg0)
{
argv0 = arg0;
}
void err_error(const char *fmt, ...)
{
fprintf(stderr, "%s: ", argv0);
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
exit(EXIT_FAILURE);
}
void err_syserr(const char *fmt, ...)
{
int errnum = errno;
fprintf(stderr, "%s: ", argv0);
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, "(%d: %s)", errnum, strerror(errnum));
putc('\n', stderr);
exit(EXIT_FAILURE);
}
Configuration header — posixver.h
You can adjust the higher version number to 700 (for POSIX 2008/2013) on many systems, but it probably isn't a good idea on Mac OS X, even with 10.10.3 Yosemite.
#ifndef JLSS_ID_POSIXVER_H
#define JLSS_ID_POSIXVER_H
#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE)
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600
#else
#define _XOPEN_SOURCE 500
#endif
#endif
In all cases, the 'real' code includes (a few) comments and other explanations of what's going on. The production stderr.h
and stderr.c
are more complex than the minimal version shown, but for many purposes, what's shown is equivalent to the production version.
Example run
$ ./shm-master -H
./shm-master: invalid option -- 'H'
Usage: ./shm-master [-adx][-f file][-s size][-i id]
$ ./shm-master -ax
./shm-master: 2 of 3 mutually exclusive options -a, -d and -x specified
$ ./shm-master -dx
./shm-master: 2 of 3 mutually exclusive options -a, -d and -x specified
$ ./shm-master -da
./shm-master: 2 of 3 mutually exclusive options -a, -d and -x specified
$ ./shm-master -dax
./shm-master: 3 of 3 mutually exclusive options -a, -d and -x specified
$ ipcs -m | grep -v '^0x00000000 '
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x620010f7 0 root 660 557920 4
0x63002725 32769 root 666 82164 3
$ ./shm-master -x
ID: 0, File: /etc/passwd
Key: 0x0000009F
ShmID: 44793901
Shared memory allocated at 0x7F29AC43A000
Detached from shared memory
$ ipcs -m | grep -v '^0x00000000 '
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x620010f7 0 root 660 557920 4
0x63002725 32769 root 666 82164 3
0x0000009f 44793901 jleffler 600 65536 0
$ ./shm-master -d
ID: 0, File: /etc/passwd
Key: 0x0000009F
ShmID: 44793901
Shared memory removed
$ ipcs -m
$ grep -v '^0x00000000 '
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x620010f7 0 root 660 557920 4
0x63002725 32769 root 666 82164 3
$ ./shm-master -f /home/jleffler/soq/shm-master -a
./shm-master: Failed to get shared memory ID: (2: No such file or directory)
ID: 0, File: /home/jleffler/soq/shm-master
Key: 0x00010FB9
$ ./shm-master -f /home/jleffler/soq/shm-master -d
./shm-master: Failed to get shared memory ID: (2: No such file or directory)
ID: 0, File: /home/jleffler/soq/shm-master
Key: 0x00010FB9
$ ./shm-master -f /home/jleffler/soq/shm-master -x
ID: 0, File: /home/jleffler/soq/shm-master
Key: 0x00010FB9
ShmID: 44826669
Shared memory allocated at 0x7FA1488CA000
Detached from shared memory
$ ./shm-master -f /home/jleffler/soq/shm-master -d
ID: 0, File: /home/jleffler/soq/shm-master
Key: 0x00010FB9
ShmID: 44826669
Shared memory removed
$ ./shm-master -f /home/jleffler/soq/shm-master -x
ID: 0, File: /home/jleffler/soq/shm-master
Key: 0x00010FB9
ShmID: 44859437
Shared memory allocated at 0x7F93005EC000
Detached from shared memory
$ shmid=$(./shm-master -f /home/jleffler/soq/shm-master -a sed -n '/ShmID: /s///p')
$ ipcs -m -i $shmid
Shared memory Segment shmid=44859437
uid=199484 gid=5000 cuid=199484 cgid=5000
mode=0600 access_perms=0600
bytes=65536 lpid=31202 cpid=31200 nattch=0
att_time=Fri Apr 17 11:37:06 2015
det_time=Fri Apr 17 11:37:06 2015
change_time=Fri Apr 17 11:37:06 2015
$ ./shm-master -f /home/jleffler/soq/shm-master -d
ID: 0, File: /home/jleffler/soq/shm-master
Key: 0x00010FB9
ShmID: 44859437
Shared memory removed
$
Incidentally, the ipcs
option -i id
is a Linux extension over the POSIX specification for ipcs, and the option is not available on, for example, Mac OS X (BSD). The nearest equivalent would be something like ipcs -m -a | grep "$shmid"
, which isn't perfect. The grep -v '^0x00000000 '
operations eliminate the private shared memory segments (there were a lot of them in use on the machine I did the testing on).
来源:https://stackoverflow.com/questions/29691159/making-a-shared-data-structure-in-c