Zde je příklad sdílené paměti:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHM_SIZE 1024 /* make it a 1K shared memory segment */
int main(int argc, char *argv[])
{
key_t key;
int shmid;
char *data;
int mode;
if (argc > 2) {
fprintf(stderr, "usage: shmdemo [data_to_write]\n");
exit(1);
}
/* make the key: */
if ((key = ftok("hello.txt", 'R')) == -1) /*Here the file must exist */
{
perror("ftok");
exit(1);
}
/* create the segment: */
if ((shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT)) == -1) {
perror("shmget");
exit(1);
}
/* attach to the segment to get a pointer to it: */
if ((data = shmat(shmid, NULL, 0)) == (void *)-1) {
perror("shmat");
exit(1);
}
/* read or modify the segment, based on the command line: */
if (argc == 2) {
printf("writing to segment: \"%s\"\n", argv[1]);
strncpy(data, argv[1], SHM_SIZE);
} else
printf("segment contains: \"%s\"\n", data);
/* detach from the segment: */
if (shmdt(data) == -1) {
perror("shmdt");
exit(1);
}
return 0;
}
Kroky:
-
Pomocí ftok převeďte cestu a identifikátor projektu na klíč System V IPC
-
Použijte shmget, který alokuje segment sdílené paměti
-
Použijte shmat k připojení segmentu sdílené paměti označeného shmid k adresnímu prostoru volajícího procesu
-
Proveďte operace v oblasti paměti
-
Odpojit pomocí shmdt
Existují dva přístupy:shmget
a mmap
. Budu mluvit o mmap
, protože je modernější a flexibilnější, ale můžete se podívat na man shmget
(nebo tento tutoriál), pokud byste raději používali nástroje starého stylu.
mmap()
funkci lze použít k přidělení vyrovnávacích pamětí s vysoce přizpůsobitelnými parametry pro řízení přístupu a oprávnění a v případě potřeby k jejich zálohování úložištěm souborového systému.
Následující funkce vytvoří vyrovnávací paměť v paměti, kterou může proces sdílet se svými potomky:
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
void* create_shared_memory(size_t size) {
// Our memory buffer will be readable and writable:
int protection = PROT_READ | PROT_WRITE;
// The buffer will be shared (meaning other processes can access it), but
// anonymous (meaning third-party processes cannot obtain an address for it),
// so only this process and its children will be able to use it:
int visibility = MAP_SHARED | MAP_ANONYMOUS;
// The remaining parameters to `mmap()` are not important for this use case,
// but the manpage for `mmap` explains their purpose.
return mmap(NULL, size, protection, visibility, -1, 0);
}
Následuje příklad programu, který používá výše definovanou funkci k přidělení vyrovnávací paměti. Rodičovský proces napíše zprávu, rozdělí a pak počká, až jeho podřízený proces upraví vyrovnávací paměť. Oba procesy mohou číst a zapisovat sdílenou paměť.
#include <string.h>
#include <unistd.h>
int main() {
char parent_message[] = "hello"; // parent process will write this message
char child_message[] = "goodbye"; // child process will then write this one
void* shmem = create_shared_memory(128);
memcpy(shmem, parent_message, sizeof(parent_message));
int pid = fork();
if (pid == 0) {
printf("Child read: %s\n", shmem);
memcpy(shmem, child_message, sizeof(child_message));
printf("Child wrote: %s\n", shmem);
} else {
printf("Parent read: %s\n", shmem);
sleep(1);
printf("After 1s, parent read: %s\n", shmem);
}
}