thread 함수 내에서의 extern 변수 선언이 갖는 의미?

citigambler의 이미지

안녕하세요..
간만에 C 프로그래밍을 하려니 가물가물 확실하지 않은 점이 있어 한번 문의 드려 봅니다.

1. a.c

int session;
 
int init_session(int n)
{
    session = n;
}

2. b.c

do_main_thread()  <-- pthread_create()의 구동 함수라고 가정
{
    extern int session;
    init_session(1);
    do_process();
}
 
void do_process() <-- 인자로 session을 넘기지 않음
{
    do something using "session"
}

위와 같은 코드가 있다고 하고 b.c의 thread는 두개라고 가정(do_main_thread가 두번 call)하고요..

여기서 질문은:
1. b.c의 do_main_thread() 내에서 a.c의 session을 extern을 선언하면 내부의 do_process()에서 a.c의 session 변수를 access 가능 할런지요?
2. thread 사이에 session 변수가 공유 될런지요?

위 코드의 목적은 multithread 환경에서 각 thread들이 a.c의 session을 각각 사용하게 하는데 있으며 또한 thread 내 다른 함수들 사이에 인자 전달 없이 session을 access 하게 만드는데 있습니다.

테스트 환경을 사용이 어려운 상황이라 어렵네요.. ㅜㅜ

pajaebeo의 이미지

int session; 이 global이므로 당연히 되지만요..

session 값의 변경을 양 쓰레드가 모두 잘 인지하기 위해서는
'volatile'로 선언해 주시고, semaphore 같은 걸로 묶어 주시면 될 것 같습니다.
(r/w가 thread간에 atomic 처럼 동작하도록요..)

citigambler의 이미지

근데 여기서 목적은 session을 공유 하면서 한번에 한쪽에서만 access 하게 만드는게 아니고(이부분은 mutex로 이미 구현 가능하겠죠..) 두개의 thread가 "각각"의 session variable을 가지고 각자 활동을 하게 하고 싶거든요..

session을 global로 해놔서 혹시 session이 두 thread 사이에 공유 된다면 망치는 거라 이부분이 어떻게 되는것인지..

bushi의 이미지

thread local storage 를 원하시는 것 같습니다. 줄여서 TLS 라 표기합니다.
pthread_key_create(), pthread_setspecific(), pthread_getspecific()

OTL

citigambler의 이미지

저도 TLS를 사용하고 싶은데 TLS는 위 예에서와 같은 다른 object에서 선언된 공용변수를 지정해봐야 의미가 없지 않은지요?
thread 내에서 선언된 private 변수를 하위 함수들에서 access 하기 위해서 TLS로 지정, 계속 Access 하는건 좋은데 이 경우는 변수 자체가 외부 object에 선언된(extern으로 끌고 오죠.. ㅜㅜ)전역 변수이나 thread 내부에서는 TLS처럼 사용할수 있는 방법이 있는지 찾는 중입니다.

요지는 session과 init_session()을 다른 파일에 선언하고 extern으로 끌고와서 사용하면서 다른 thread와 공유되지 않게 하는 방법(thread 별로 따로 고유의 session(변수)을 유지 하는 방법)을 찾는 것입니다.

jick의 이미지

extern은 그냥 "이 컴파일 유닛엔 없지만 다른 어딘가에 이 변수가 있으니 없다고 에러 내지 말라"라는 얘기일 뿐입니다. 뭘 끌어온다든지 하는 "동작"을 하지 않습니다.

그러니까 TLS로 쓰고 싶으시면 그 변수를 정의하는 곳에서 TLS로 정의해야 합니다.

* (제가 아는 한) 표준은 아니지만... 많은 곳에서 돌아가는 방식으로 __thread라는 기능이 있습니다. __thread int i; 이런 식으로 변수를 만들면 자동으로 TLS가 돼서 서로 다른 쓰레드는 서로 다른 i 변수를 보게 됩니다. pthread_getspecific 등등보다는 훨씬 쓰기 편하고 (일반적으로) 속도도 더 빠릅니다.

citigambler의 이미지

__thread를 기입해서 써보려 하니 아래와 같이 오류가 나오네요..

extern __thread int sessio;

/rktikr1/kti2/src/kc96080>cc b.c -o b -lpthread
/usr/ccs/bin/ld: TP/DTV override with DP_REL fixup for non thread local storage symbol session in file b.o

/rktikr1/kti2/src/kc96080>cc a.o b.o -o test_a_b -lpthread
/usr/ccs/bin/ld: TP/DTV override with DP_REL fixup for non thread local storage symbol session in file b.o

HP UNIX에서는 안되는 건가.. ㅜㅜ b.o는 생기기는 했는데 test_a_b는 안생기네요..

구글 찾아 봐도 이 에러는 안나오는걸 보니 보통에러는 아닌듯 한디.. 고민스럽네요.. ㅜㅜ

라스코니의 이미지

class 를 만드시면 되겠습니다. 이경우에도 do_process()에 인자로 객체 포인터는 넘겨야 할 것 같은데요....

c 언어이고, do_process() 에 인자를 넘겨줄 수 없는 상황이라면,,,

session 을 동적으로 생성하고 stl std::map 과 같은 linked list 를 만드는 겁니다. key 는 thread_id 로 주어야 겠죠.

do_process() 내에서 자신이 돌고 있는 thread_id 를 검출해서 session 에 접근하면 될 것 같습니다.

citigambler의 이미지

사실 현재 그렇게 사용을 하고 있는데 이를 thread 방식으로 바꾸면서는 원 구조를 좀 탈피 하고자 하거든요..
thread_once 에서 init 하고 각 thread에서 mutex 걸고 session하나씩 setup 하면 되긴 하겠지만 그러면 후에 다른 function들에서 session을 찾아야 한다는 번거로움 및 thread 개수와 session 개수를 맞추기도 문제고 해서요..(thread 개수가 외부 middleware에 의해서 setup이 되서 내부 pgm에 전달이 안됩니다.. ㅜㅜ thread가 몇개가 생길지 pgm에서는 모르니 session배열의 개수를 지정할수가 없죠..)

라스코니의 이미지

이용해서 쉽게 하실 수 있는데요.

C 로만 해야 한다고 본다면 역시 동적 linked list 를 고려해보시는 것도 좋을 듯 싶습니다.

제가 보기에 linked list 의 중간 삭제 이런 것 없이 추가만 되면 되는 구조인 것 같으니 메인 session linked list 만 처음에 blank 로 잡아놓고 thread 가 생성될 때마다 동적 list 를 생성해서 추가(추가할 때 당연히 main session list 에 mutex 걸어 놓고 해야 겠지요)하고, 각 thread 에서 마음놓고 쓰면 될 것 같습니다. 각 thread 가 독점 list 를 가지고 있으니 mutex 를 써야 할 필요도 없지요.

jinseo1224의 이미지

a.c에 선언된 int session를
b.c에서 extern 으로 사용하는것 자체가 a.c와 b.c에서 함께 사용하겠다는 것이 됩니다.
c.c에서 extern 으로 사용을 한다면 a.c, b.c, c.c 세가지에서 사용되는 session의 값은 같겠지요.

b.c 안에서 스레드이던 아니던간에 session값을 변경하면 a.c, c.c에서도 b.c에서 변경된 session 값을 사용하게됩니다.
이와 마찬가지로
b.c 안에서 스레드 b-1 이 session값을 바꾼다면 session을 이용하는 모든 스레드들이 b-2, b-3, b-4)
b-1스레드가 변경한 session값을 사용하게 됩니다. a.c 와 c.c 또한 b-1스레드가 변경한 session값을 사용하겠지요.

따라서 질문자님이 말씀하신
"두개의 thread가 "각각"의 session variable을 가지고 각자 활동을 하게 하고 싶거든요.." 가 수행 되려면

int session 의 선언이 a.c가 아닌 b.c의 스레드안에서 이루어 지고
a.c의 init_session함수가 인자를 받아 처리를한후 세션을 return 하도록 변경되어야 합니다.

int init_session(int n)
{
int session = n;
return session;
}

즉, 스레드 b-1은 int session = init_session(int n);
스레드 b-2도 int session = init_session(int n);
c.c도 int session = init_session(int n);
처럼 사용한다면
같은 init 철차를 수행하여 스레드b-1, b-2 그리고 c.c가 '각각'의 session을 보유할 수 있게 됩니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.