2009-11-04 16 views
6

Próbuję napisać program, w którym procesy potomne komunikują się ze sobą w systemie Linux.Jak zachować int i tablicę we wspólnej pamięci w C?

Wszystkie te procesy są tworzone z tego samego programu i jako takie udostępniają kod.

Potrzebuję ich do uzyskania dostępu do dwóch zmiennych liczb całkowitych oraz tablicy liczb całkowitych.

Nie mam pojęcia, jak działa pamięć współdzielona i każdy zasób, którego szukałem, nie zrobił nic, tylko wprowadził mnie w błąd.

Każda pomoc będzie bardzo ceniona!

Edytuj: Oto przykład kodu, który napisałem do tej pory, aby udostępnić jedną int, ale prawdopodobnie jest błędna.

int segmentId; 
int sharedInt; 
const int shareSize = sizeof(int); 
/* Allocate shared memory segment */ 
segmentId = shmget(IPC_PRIVATE, shareSize, S_IRUSR | S_IWUSR); 

/* attach the shared memory segment */  
sharedInt = (int) shmat(segmentId, NULL, 0); 

/* Rest of code will go here */ 

/* detach shared memory segment */ 
shmdt(sharedInt); 
/* remove shared memory segment */ 
shmctl(segmentId, IPC_RMID, NULL); 
+4

Który system operacyjny? –

+1

Mój błąd. To jest na Linuksie – Josh

+0

Zauważ to pytanie od wczoraj: http://stackoverflow.com/questions/1664519/creating-accessing-shared-memory-in-c (ten sam ogólny temat, chociaż wybrałeś Sys V IPC). –

Odpowiedz

6

Będziesz potrzebował zwiększyć rozmiar swojej wspólnej pamięci. Jak duża tablica potrzebujesz? Bez względu na to, jaka jest wartość, musisz wybrać ją przed utworzeniem segmentu pamięci współużytkowanej - pamięć dynamiczna nie będzie tutaj działała zbyt dobrze.

Po podłączeniu do pamięci współdzielonej otrzymasz wskaźnik do adresu początkowego. Będzie wystarczająco dobrze wyrównany, aby można go było wykorzystać w dowolnym celu. Możesz więc tworzyć wskaźniki dla twoich dwóch zmiennych i tablic wzdłuż tych linii (przyklejając niektóre szkielety z przykładu kodu) - zwróć uwagę na użycie wskaźników do dostępu do pamięci współdzielonej:

enum { ARRAY_SIZE = 1024 * 1024 }; 
int segmentId; 
int *sharedInt1; 
int *sharedInt2; 
int *sharedArry; 

const int shareSize = sizeof(int) * (2 + ARRAY_SIZE); 
/* Allocate shared memory segment */ 
segmentId = shmget(IPC_PRIVATE, shareSize, S_IRUSR | S_IWUSR); 

/* attach the shared memory segment */  
sharedInt1 = (int *) shmat(segmentId, NULL, 0); 
sharedInt2 = sharedInt1 + 1; 
sharedArry = sharedInt1 + 2; 

/* Rest of code will go here */ 
...fork your child processes... 
...the children can use the three pointers to shared memory... 
...worry about synchronization... 
...you may need to use semaphores too - but they *are* complex... 
...Note that pthreads and mutexes are no help with independent processes... 

/* detach shared memory segment */ 
shmdt(sharedInt1); 
/* remove shared memory segment */ 
shmctl(segmentId, IPC_RMID, NULL); 
+0

To wygląda całkiem świetnie. Dzięki wielkie! – Josh

0

Ten podręcznik wygląda użytecznie: http://www.cs.cf.ac.uk/Dave/C/node27.html. Zawiera kilka przykładowych programów.

Istnieje również Linux man pages online.

+0

Dzięki, ale niestety jest to jedna z tych stron, które całkowicie mnie pomyliły. – Josh

+0

Czy próbowałeś skopiować i wkleić tam przykładowy kod i skompilować go? Jeśli możesz to skompilować, prawdopodobnie jesteś w połowie drogi do zrozumienia. –

+0

Mój problem z tym przykładem jest taki, że wygląda na to, że różne programy rozmawiają w sposób klient-serwer. Nie wyjaśniłem, czego potrzebuję w czasie mojego pierwotnego pytania, ale w moim kodzie będę tworzyć wiele procesów z tego samego programu i potrzebuję ich do komunikacji. – Josh

0

Pamięć współdzielona to tylko segment pamięci przydzielony przez jeden proces, o unikalnym identyfikatorze, a drugi proces powoduje również, że przydział o tym samym id, a rozmiar pamięci jest wielkością struktury, którą używają, więc będziesz miał strukturę z 2 liczbami całkowitymi i tablicą całkowitą.

Teraz obaj mają wskaźnik do tej samej pamięci, więc zapis jednego z nich zastąpi wszystko, co tam było, a drugi ma natychmiastowy dostęp do niego.

+0

@Josh no, formatowanie komentarza wysysa spleśniałe skały - ale wtedy musisz edytować swoje pytanie, aby je wyjaśnić, zamiast komentować, aby móc ładnie sformatować swój kod w edycji odpowiedzi i usunąć te komentarze! –

+0

Zalecam, aby dodać wyjaśnienie do pierwotnego pytania. –

+0

@Josh - możesz zajrzeć do tego samouczka: http://www.ecst.csuchico.edu/~beej/guide/ipc/shmem.html, ponieważ pokazuje również, jak używać ftok do tworzenia klucza do połączenie. –

0

Z Twojego komentarza wynika, że ​​używasz IPC_PRIVATE, a to zdecydowanie wygląda źle ("prywatne" rodzaje sugerują, że nie są przeznaczone do udostępniania, nie?). Wypróbuj coś takiego:

#include <sys/ipc.h> 
#include <sys/shm.h> 

... 

int segid = shmget((key_t)0x0BADDOOD, shareSize, IPC_CREAT); 
if (segid < 0) { /* insert error processing here! */ } 
int *p = (int*) shmat(segid, 0, 0); 
if (!p) { /* insert error processing here! */ } 
+0

To wygląda interesująco. Nie jestem najlepszy jeśli chodzi o C, więc czy w tym przypadku będzie to tablica int? Ciekawi mnie również wartość heksadecymalna w shmget. – Josh

+0

IPC_PRIVATE działa, jeśli rodzic utworzy pamięć współużytkowaną, a następnie wyświetli listę dzieci, które zamierzają ją udostępnić. –

+0

@ Jos: potrzebna jest 32-bitowa wartość jako klucz do pamięci współużytkowanej. Możesz użyć ftok(), aby utworzyć, lub wybrać stałą nazwę. Żaden Bad Dood nie jest tak dobrym imieniem, jak każdy inny element pamięci współdzielonej. 0xDEADBEEF to kolejna dobrze znana wartość. Ale IPC_PRIVATE jest również dobry - tak długo, jak proces rodzica tworzy i łączy pamięć współdzieloną przed rozwidleniem. –

Powiązane problemy