Я пытаюсь понять, как работают внешние переменные при использовании динамического связывания и динамической загрузки разделяемых библиотек, и могут ли быть проблемы с большой наследованной кодовой базой, которую я унаследовал. К сожалению, я не могу поделиться кодом из этой кодовой базы и хочу выяснить, есть ли здесь особая проблема. Я хотел бы знать, может ли переменная, которая является частью общей библиотеки, видоизменяться из нескольких процессов, которые динамически загружают общую библиотеку.
Это файл main.c.
// main.c
#include <stdio.h>
#include <unistd.h>
#include "foo.h"
int main(void)
{
while(1){
printf("Value = %d\n", global);
foo();
}
return 0;
}
Это файл foo.c.
// foo.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int global = 0;
void foo(void)
{
global = global + 1;
sleep(1);
}
и это файл foo.h.
// foo.h
#ifndef foo_h__
#define foo_h__
extern void foo(void);
extern int global;
#endif // foo_h__
Это Makefile для компиляции этой программы.
# Makefile
all: main
main:
gcc -c -Wall -Werror -fpic foo.c
gcc -shared -o libfoo.dylib foo.o
gcc -Wall -o test main.c -lfoo -L.
Поскольку переменная global
имеет внешнее определение, и поскольку создается разделяемая библиотека, я ожидал, что код сломается при запуске в нескольких процессах. Однако, если я открываю два терминала и запускаю ./test
на обоих из них одновременно, счетчик увеличивается независимо и правильно (нет общей разделяемой памяти). Я рад, что это так, но мне интересно, есть ли способ это сломать? Прочитав эти ответы [1-2], я подумал, что память разделяемых библиотек была загружена только один раз в пространство виртуальной памяти, и я предполагал, что приведенный выше код не будет работать, т.е. при запуске второго процесса первый процесс будет сбросить в ноль. Как заставить этот код выше увеличить значение в одном и том же адресе памяти в разных процессах? Возможно ли это вообще?
[1] https://stackoverflow.com/a/19374253/5451769
[2] https://softwareengineering.stackexchange.com/a/244666