[완료]glibc 의 pthread_mutex 에 변수 하나 추가하는것도 절대 안되는건가요?

bily의 이미지

일반적으로 스레드 프로그래밍을 할때 쓰는 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");

라는 디버깅 구문을 추가해봐도 죽기 전에 나오지 않는걸로 봐서, 이부분도 아닌듯 합니다.

디버깅 하기 어렵네요.

뭔가 제가 모르는 시스템적인 커널과 프로세스의 디자인 원칙이 있는듯 하기도 한데, 도대체 이게 뭔지 알수가 없네요.

bushi의 이미지

... 예를 하나 들죠.
liba 를 사용하는 어플리케이션을 다음과 같이 작성해서 컴파일했습니다.

[a_app.c] ----------
struct a my_a;
 
int my_func(void)
{
   return liba_init(&my_a);
}

liba 는 원래 이랬습니다.

[a.h] ----------
struct a {
 int i;
 char c[4];
};
----------------
[a.c] -----------
int liba_init(struct a *a)
{
   memset(a, 0, sizeof(*a));
   a->c[0] = '1';
   return 0
}
-----------------

그런데, 어느날 갑자기 불현듯 땡겨서

[a.h] ------------
struct a
{
  int i;
  unsigned int ui;
  char c[8];
};
------------------
처럼 수정을 하고 liba 를 다시 컴파일했습니다.

예전에 컴파일 해놨던 a_app 의 my_a 는 어떻게 되겠습니까 ?

OTL

bily의 이미지


답변 감사드립니다.

말씀해 주신대로, 기존의 프로그램들은 seg fault가 나는것을 이해 하겠습니다.

그러나,

라이브러리를 새로 컴파일 한 후에, 응용 프로그램 역시 새로운 라이브러리를 사용하도록 하기 위해서, -I 옵션으로 include, -L 옵션으로 lib를 주었습니다.

그렇다면, 새로 컴파일된 응용 프로그램의 스레드 프로그래밍에서는 , 이제는 라이브러리의 구조가 바뀐것을 알고 있을테니, 에러가 없어야 하지 않을까요?

bushi의 이미지

gcc 의 -L 옵션은 링커가 참조할 경로의 우선순위를 지정하는 데 사용합니다.
로더가 참조하는 경로의 우선순위는 LD_LIBRARY_PATH 환경변수로 조작할 수 있습니다.

OTL

bily의 이미지


답변 감사드립니다.

gcc 옵션을 새로 컴파일한 라이브러리로 맞춰 주고, 로더가 참조하도록 LD_LIBRARY_PATH로 새로 컴파일된 경로를 지정해 주었습니다만,

여전히 안되네요. 프로세스 생성을 하던가 할때, assert 같은걸로 뮤텍스의 사이즈를 체크 하는 부분이라도 어딘가에 있나 봅니다. 저는 찾지 못했지만..

무슨 제약이 있는듯 합니다.

bushi의 이미지

이게 뭔짓인지 모르겠지만... 간만에 대량의 컴파일 메시지 주루룩 올라가는 것을 볼수있어 약간의 자극은 된 것 같습니다.
glibc-2.7 을 말씀하신대로 수정해서 컴파일했고, 테스트에 사용한 코드는 다음과 같습니다.

#include <stdio.h>
#include <pthread.h>
 
/* pthred_mutex_t was changed.
 * so, do not use PTHREAD_MUTEX_INITIALIZER family
 */
 
void *thread_proc(void *arg)
{
   int i;
   pthread_mutex_t *mutex = arg;
 
   for (i=0; i<100;i++) {
      pthread_mutex_lock(mutex);
      mutex->__data.a++;
      pthread_mutex_unlock(mutex);
      usleep(1000);
   }
 
   return NULL;
}
 
int main()
{
   int ret;
   pthread_t tid[100];
   pthread_mutex_t mutex;
 
   int i;
 
   pthread_mutex_init(&mutex, NULL);
 
   mutex.__data.a = 0;
 
   for (i=0; i<100; i++) {
      ret = pthread_create(&tid[i], NULL, thread_proc, &mutex);
      if (ret) {
         perror("pthread_create");
         break;
      }
      usleep(1000);
   }
   for (; i>0;i--) {
      pthread_join(tid[i-1], NULL);
   }
 
   printf("%d\n", mutex.__data.a);
 
   return 0;
}

컴파일해서 실행시켜봤습니다.

[bushi@rose test]$ gcc -g -o test test.c -I../glibc-test/install/include -L../glibc-test/install/lib -lpthread
[bushi@rose test]$../glibc-test/install/lib/ld-2.7.so ./test
10000
[bushi@rose test]$ 

데스크탑은 fedora10 이고, 이놈의 glibc-2.9 환경입니다.
최대한 간단하게 테스트하느라 테스트용의 glibc-2.7 빌드시엔 selinux 를 뺐습니다.

OTL

bily의 이미지

컴파일 하시면서, 몇가지 에러도 만나셨을텐데.. 시간내서 확인까지 해주시다니, 감사 드립니다.

해당하는 프로그램을 돌리니, 실행이 됩니다.

기존의 제가 했던 부분과의 차이점은,

1. test 프로그램의 디렉토리 또한, glibc-2.7 아래에 두었다는 점과

2. gcc의 옵션 순서가 다르다는 점 두가지 입니다.

3. 기존 리눅스가 glibc-2.7을 쓰기에 ld-2.7.so 부분은 사용치 않았습니다.

결국, 테스트 프로그램이 glibc 디렉토리 아래에 있지 않았다 또는 옵션 순서가 달랐다라는 당황스런 결과에 이르게 되네요.

덕분에 많이 배웠습니다.다시 한번 감사드립니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.