[완료]glibc 의 pthread_mutex 에 변수 하나 추가하는것도 절대 안되는건가요?
일반적으로 스레드 프로그래밍을 할때 쓰는 pthread_mutex_lock 함수를 조금 바꿔 볼까 해서..
glibc-2.7을 다운 받아서, nptl 디렉토리를 살펴 보고 있습니다.
nptl/pthread_mutex_lock.c 파일에서 __pthread_mutex_lock()에서 pthread_mutex_t자료 구조를 넘겨서 뮤텍스로 사용하고 있는것을 보고,
glibc-2.7/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h 파일의 struct __pthread_mutex_s로 선언된 pthread_mutex_t자료 구조를
조금 바꿔 볼까 하고 있습니다.
..
그래서, 뮤텍스 구조체에, int a 변수 하나만 추가해서, glibc 컴파일까지는 성공 했습니다. make install 로 다른 디렉토리에 설치하고, 응용 프로그램 컴파일 할때,
옵션으로 새로운 라이브러리를 include 하도록 했습니다. 그리고 나서, LD_LIBRARY_PATH 또한, 새로이 인스톨 된 디렉토리를 가리키도록 하였습니다. 하지만, 다른 모
든 커맨드까지 segmentation fault가 나는것으로 봐서, 뭔가 잘못 된듯 합니다. 세그 폴트 나는 커맨드들을 ldd로 확인해 보니, libpthread를 사용하더군요.
..
이해 되지 않는것은,
제가 고친것은 구조체에 int a; 추가한 것이고, 그만큼 사이즈를 늘려줘서서 컴파일도 문제도 없이 했는데, 어디가 잘못 된건지 찾기가 너무 어렵네요.
libc-2.7/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h파일에서 제가 바꾼 코드는 다음과 같습니다.
아래 코드 가운데 쯤에 *********로 감싸줘 있습니다.
/* Data structures for mutex handling. The structure of the attribute
type is not exposed on purpose. */
typedef union
{
struct __pthread_mutex_s
{
int __lock;
unsigned int __count;
int __owner;
#if __WORDSIZE == 64
unsigned int __nusers;
#endif
/* KIND must stay at this position in the structure to maintain
binary compatibility. */
int __kind;
#if __WORDSIZE == 64
int __spins;
__pthread_list_t __list;
# define __PTHREAD_MUTEX_HAVE_PREV 1
#else
unsigned int __nusers;
__extension__ union
{
int __spins;
__pthread_slist_t __list;
};
#endif
**********************
int a; <- 여기 변수 추가
*********************
} __data;
char __size[__SIZEOF_PTHREAD_MUTEX_T];
long int __align;
} pthread_mutex_t;
그리고, 기존의 # define __SIZEOF_PTHREAD_MUTEX_T 40 를 # define __SIZEOF_PTHREAD_MUTEX_T 40+sizeof(int)
바꿔서 int를 추가한 만큼의 사이즈를 증가 시켰습니다.
..
결국, 의문점은 mutex 구조체에 변수 추가조차 안되도록 어디선가 막아놓은 건가요? 어떻게 해결할수 없을까요?
추측의 답변도 감사히 듣겠습니다.
***************************************
계속 테스트 중인데,
# define __SIZEOF_PTHREAD_MUTEX_T 40 에서 40이라는 크기를 다른 수로 바꾸기만 해도
seg fault를 내는군요. 그런데, 리눅스 코드 내에서도 그렇고, glibc 전체를 grep를 해봐도 어디에도 저 선언을 사용하는 코드는 나타 나질 않습니다.
glibc 코드 가운데, pthread_mutex_init.c 코드내에서,
assert (sizeof (pthread_mutex_t) <= __SIZEOF_PTHREAD_MUTEX_T);
라는 부분이 있지만, 바로 위에 printf("mutex_init.c, before assert\n");
라는 디버깅 구문을 추가해봐도 죽기 전에 나오지 않는걸로 봐서, 이부분도 아닌듯 합니다.
디버깅 하기 어렵네요.
뭔가 제가 모르는 시스템적인 커널과 프로세스의 디자인 원칙이 있는듯 하기도 한데, 도대체 이게 뭔지 알수가 없네요.
... 예를 하나
... 예를 하나 들죠.
liba 를 사용하는 어플리케이션을 다음과 같이 작성해서 컴파일했습니다.
liba 는 원래 이랬습니다.
그런데, 어느날 갑자기 불현듯 땡겨서
예전에 컴파일 해놨던 a_app 의 my_a 는 어떻게 되겠습니까 ?
OTL
답변 감사드립니다.
답변 감사드립니다.
말씀해 주신대로, 기존의 프로그램들은 seg fault가 나는것을 이해 하겠습니다.
그러나,
라이브러리를 새로 컴파일 한 후에, 응용 프로그램 역시 새로운 라이브러리를 사용하도록 하기 위해서, -I 옵션으로 include, -L 옵션으로 lib를 주었습니다.
그렇다면, 새로 컴파일된 응용 프로그램의 스레드 프로그래밍에서는 , 이제는 라이브러리의 구조가 바뀐것을 알고 있을테니, 에러가 없어야 하지 않을까요?
gcc 의 -L 옵션은
gcc 의 -L 옵션은 링커가 참조할 경로의 우선순위를 지정하는 데 사용합니다.
로더가 참조하는 경로의 우선순위는 LD_LIBRARY_PATH 환경변수로 조작할 수 있습니다.
OTL
네. 감사드립니다.
답변 감사드립니다.
gcc 옵션을 새로 컴파일한 라이브러리로 맞춰 주고, 로더가 참조하도록 LD_LIBRARY_PATH로 새로 컴파일된 경로를 지정해 주었습니다만,
여전히 안되네요. 프로세스 생성을 하던가 할때, assert 같은걸로 뮤텍스의 사이즈를 체크 하는 부분이라도 어딘가에 있나 봅니다. 저는 찾지 못했지만..
무슨 제약이 있는듯 합니다.
이게 뭔짓인지
이게 뭔짓인지 모르겠지만... 간만에 대량의 컴파일 메시지 주루룩 올라가는 것을 볼수있어 약간의 자극은 된 것 같습니다.
glibc-2.7 을 말씀하신대로 수정해서 컴파일했고, 테스트에 사용한 코드는 다음과 같습니다.
컴파일해서 실행시켜봤습니다.
데스크탑은 fedora10 이고, 이놈의 glibc-2.9 환경입니다.
최대한 간단하게 테스트하느라 테스트용의 glibc-2.7 빌드시엔 selinux 를 뺐습니다.
OTL
답변 감사합니다.
컴파일 하시면서, 몇가지 에러도 만나셨을텐데.. 시간내서 확인까지 해주시다니, 감사 드립니다.
해당하는 프로그램을 돌리니, 실행이 됩니다.
기존의 제가 했던 부분과의 차이점은,
1. test 프로그램의 디렉토리 또한, glibc-2.7 아래에 두었다는 점과
2. gcc의 옵션 순서가 다르다는 점 두가지 입니다.
3. 기존 리눅스가 glibc-2.7을 쓰기에 ld-2.7.so 부분은 사용치 않았습니다.
결국, 테스트 프로그램이 glibc 디렉토리 아래에 있지 않았다 또는 옵션 순서가 달랐다라는 당황스런 결과에 이르게 되네요.
덕분에 많이 배웠습니다.다시 한번 감사드립니다.
댓글 달기