Избягвайте дублиране на променливи, като използвате fork() в C

Внедрявам сървър, който обслужва множество клиенти и имам нужда от променлива на сървъра да бъде в споделена памет, така че клиентът действително да вижда какво е редактирал друг клиент в крайна сметка.

Опитах се да се огледам, но не разбрах дали има някакъв начин да постигна това с помощта на fork() или трябва напълно да променя начина, по който се справям с клиентите. По-специално, не знам дали трябва да внедря предадени процеси или нишки. Също така, кой е по-простият начин?

Това е моят код след деклариране на int var в main:

while(1) {
        printf("Waiting connection...\n");
        if ((connfd = accept(listenfd, (struct sockaddr *) NULL, NULL)) < 0) {
            perror("Accept Error");
            exit(1);
        }

        if ((pid = fork()) == 0) {
            close (listenfd);
            printf("Variable: %d\n", var); // var = 0
            var = 1;
            printf("Variable: %d\n", var); // var = 1
            exit(0);
        }

        close(connfd);
    }

Когато се свържа с друг клиент, виждам отново var = 0, защото детето генерира копие на родителския процес.

Опитах да използвам статични или да декларирам глобални променливи извън main(), но както разбрах, няма ефект.


person wiredmark    schedule 03.02.2015    source източник
comment
Имам нужда от променлива на сървъра да бъде в споделената памет - това би било отговорът на това, което се опитвате да направите, така че не е ясно какъв е въпросът. Споделените данни между процесите трябва да се споделят по някакъв начин и споделената памет е често срещан избор.   -  person WhozCraig    schedule 03.02.2015
comment
Търсейки в мрежата, намерих това cs.cf.ac.uk/Dave /C/node27.html, но не знам дали търся правилното нещо, тъй като се говори за сегменти и подобни неща   -  person wiredmark    schedule 03.02.2015
comment
Изглежда правилно. Проверете и връзките в отговора на Basile. Разгледайте достатъчно този сайт и други и вероятно ще намерите разумни примери как да го направите.   -  person WhozCraig    schedule 03.02.2015


Отговори (1)


fork не дублира променливи, а цялото адресно пространство< /em> (по дефиниция на fork) на извикващия процес.

Може да искате да използвате малко споделена памет, но тогава трябва да ви е грижа за синхронизиране. Прочетете shm_overview(7) и sem_overview(7) (можете да споделите малко памет, като използвате mmap(2), но все пак трябва да синхронизирате).

Може би не е нужно да се разклонявате, но просто искате да имате няколко нишки, споделящи едно и също адресно пространство. Прочетете pthreads(7) и добър урок за pthread. Тогава ще трябва да се погрижите и за синхронизацията, вероятно с помощта на mutexes.

Можете също (и вместо това) да използвате друга форма на IPC. Прочетете Разширено Linux програмиране, обмислете използването на pipe(7)-s и има някои цикъл за събития около мултиплексиращо системно извикване като poll(2)

В сценарий сървър/клиент може да имате някаква заявка и протокол за запитване (от вътрешни клиенти) на някаква променлива на състоянието (вътре в сървъра).

PS. Основният проблем не е споделянето на данни, а синхронизирането и избягването на deadlock.

person Basile Starynkevitch    schedule 03.02.2015
comment
Да, знаех това. Всъщност, написах, генерира копие на родителския процес, така или иначе нямам представа как да започна с функцията, която ми написахте, можете ли да ми направите много бърз пример и да покажете как да изпращам променливите в споделеното пространство? - person wiredmark; 03.02.2015
comment
За съжаление ви трябват няколко часа четене и експериментиране. Просто не мога да направя бърз пример. синхронизациятаизбягването на блокиране) са значителни проблеми. - person Basile Starynkevitch; 03.02.2015
comment
Няма значение, просто прочетете актуализирания си отговор и ще разгледаме урока, защото на този етап не мисля, че наистина ще трябва да използвам fork, а ще създам няколко нишки. Благодаря ви за изчерпателния отговор и подкрепата - person wiredmark; 03.02.2015
comment
mmap(2) с MAP_SHARED е друга опция. Вероятно са необходими по-малко от няколко часа четене. - person mhawke; 03.02.2015
comment
@mhawke: Това, което е трудно да се разбере, е необходимостта от синхронизация и как да я приложите. - person Basile Starynkevitch; 03.02.2015
comment
@BasileStarynkevitch можеш ли да ми кажеш дали мога да използвам select() и co. да използвам нишки? - person wiredmark; 03.02.2015
comment
select IMHO е почти остарял. Използвайте poll вместо това. И да, можете да го използвате с нишки. - person Basile Starynkevitch; 03.02.2015
comment
В документацията на моя университетски учител току-що прочетох, че се предлага да се използва тази функция. Тъй като не вярвам много на това, което казва, би ли ми казал защо го смяташ за остаряло? - person wiredmark; 03.02.2015
comment
Google за проблем с C10K. Типът fd_set за select има ограничен по време на компилиране размер. - person Basile Starynkevitch; 03.02.2015
comment
Нека продължим тази дискусия в чата. - person wiredmark; 03.02.2015