Можно ли использовать атомарные встроенные функции в нескольких процессах? - PullRequest
0 голосов
/ 25 февраля 2011

Я возвращаюсь в C из .NET, поэтому, пожалуйста, прости мой код, но я пытаюсь реализовать встроенный атомарный инкремент в существующую многопроцессорную программу.

Я написал тестовую программу,и я не могу заставить его работать.Он правильно увеличивается до 5, но каждый дочерний элемент увеличивает значение до 6, а не увеличивает его до 10. Монитор отображает 5.

Я пробовал различные изменения, используя глобальный int вместо передачи статического int из mainребенку, но результат тот же.Любая помощь приветствуется, спасибо.

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <sys/types.h>
  4 #include <stdlib.h>
  5 #include <unistd.h>
  6 #include "list.h"
  7 
  8 #define N 5
  9 static int globalcount = 0;
 10 
 11 void Monitor()
 12 {
 13     sleep(1);
 14     printf("Monitor Value %d\n", globalcount);
 15 }
 16 
 17 void Child()
 18 {   
 19     int value = __sync_add_and_fetch(&globalcount, 1);
 20     printf("Child Value %d\n", value);
 21 }
 22 
 23 int main(int argc, char** argv)
 24 {
 25     int i;
 26     int value;
 27     static int count = 0;
 28     pid_t pid[N];
 29     pid_t pidkey;
 30 
 31     for (i = 0; i < N; ++i) {
 32         value = __sync_add_and_fetch(&globalcount, 1);
 33         printf("Value %d\n", value);
 34     }
 35     printf("\n\n\n");
 36 
 37     if ((pidkey = fork()) == 0) {
 38         Monitor();
 39     } else if (pidkey > 0) {
 40         for (i = 0; i < N; i++)
 41         {
 42             if ((pid[i] = fork()) == 0) {
 43                 Child();
 44                 break;
 45             }
 46         }
 47     }
 48     return 0;
 49 }   

Ответы [ 3 ]

4 голосов
/ 25 февраля 2011

Если память обслуживает меня правильно, когда вы fork() обрабатываете свой процесс, дочерний процесс получает копию переменных, точнее, переменные копируются при записи. То есть вы, по сути, ссылаетесь на одни и те же данные, пока не попытаетесь их изменить. То, что вы пытаетесь выполнить, требует большего, чем просто переменная static, объявленная в верхней части вашего кода. Вам нужно посмотреть на использование разделяемой памяти, чтобы вы могли совместно использовать переменную (и) в пространстве процесса. Поскольку это то, на что потребуется много времени, и на самом деле это не 5-строчный ответ, мне придется вернуться и отредактировать это позже с более подробной информацией. Однако, если вы посмотрите на функцию shm_get на своих страницах руководства (вместе с различными другими функциями shm_*, которые сопровождают ее), документация будет довольно обширной. В Интернете также есть несколько учебных пособий: поищите «Пример учебного пособия по совместно используемой памяти POSIX IPC», и вы получите множество обращений, описывающих, как это сделать.

2 голосов
/ 25 февраля 2011

Как Уилл говорит , дочерние процессы, созданные fork(), не зависят от своего родителя (и друг друга).Каждый из них концептуально имеет свою собственную частную копию данных, выделенную обычным способом.

Если вы хотите разделить память между процессами, вы должны явно создать область общей памяти, прежде чем вызывать fork():

int *globalcount = mmap(0, sizeof *globalcount, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
*globalcount = 0;
0 голосов
/ 25 февраля 2011

Эти атомарные операции не являются частью стандарта C, но, тем не менее, они запланированы как часть следующего стандарта.

Те, которые вы используете, выглядят так, как будто вы используете gcc? Вы действительно должны были бы искать документацию

  • ваш компилятор для атомарных примитивов и как они ведут себя с потоком разделяемой памяти (одно и то же адресное пространство) и обрабатывают разделяемую память (разные виртуальные адреса указывают на одну и ту же "физическую" память).
  • ваша ОС (unix?), Чтобы узнать, как распределяется память (или нет) после fork.
...