시그널을 이용한 프로그램에 대해서...

익명 사용자의 이미지

다음은 책의 본문중에 있는 내용입니다. 주석을 달아주세요.... ^^;
"시그널에서 주용한 문제는 '시스템 호출 과정에서 시그널이 발생한다면 어떻게 될까?'이다. 해답은 다소 복잡하게 '의존적'이라는 점이다. 일반적으로 터미널로부터 읽어들이는 것과 같이 '느린' 시스템 호출에 대해서만 걱정하면된다. 이런 경우에는 대기 상태에서 시그널이 발생한다면 시스템 호출이 에러를 반환할 것이다. 프로그램에서 시그널을 사용하기 시작하다면 시그널이전달되어 일부 시스템 호출이 실패할 수 있다는 사실을 주의할 필요가있다."
"Beginning Linux Programming - 2nd Edition, 정보문화사, p513"

익명 사용자의 이미지

signal 때문에 system call 이 실패할 수도 있다는 이야기 같네요..
"운영체제" 책에 나와있는 얘기지만 system call 은 프로세스가 운영체제
(커널) 에게 특권이 필요한 행동(예를들면 디스크에 뭔가를 기록해야 하는
행동) 을 요청할 수 있도록 운영체제에서 정의한 함수입니다.
쉽게 볼 수 있는게 write() 나 read() 같은 것들이죠...
시스템 콜은 유저 모드(맞는지..^^) 이 아닌 커널 모드에서 수행되며, 작업
이 끝나면 다시 유저 모드로 바뀌어서 시스템 콜을 호출한 프로세스가 계속
수행됩니다. 문제는 시스템 콜 중간에 시그널이 발생하면 어떻게 처리하는가..
인데 보통은 바로 시그널 핸들러가 작동하며 시스템 콜은 에러코드를 반환하며 즉시
중단됩니다.
자세한 부분은 운영체제 책을 참고하시길... 참고로 스티븐이 쓴
Advanced Programming in the Unix Environment 책에도 이 문제가 비교적
상세히 나와 있네요..

익명 사용자의 이미지

void (*signal (int sig, void (*disp)(int)))(int);

이 시그널 함수의 형식이 궁금합니다.

void형을 리턴하는 함수 포인터라는 것은 알겠습니다.
어떠한 함수가 있는데..
그 함수는 void형을 리턴 하고..
인자로는 int 형과 함수 포인터를 갖는다.

예 이해가 잘됩니다.
그런데 저어기 마지막에 붙은 (int) 이것은 이해가 되질 않습니다.

저건..왜 붙어 있는 것 일까요?

primee의 이미지

void (*signal (int sig, void (*disp)(int)))(int); 복잡하게 보이지만

간단합니다.

int sig, void (*disp)(int)) 이부분은 signal함수가 int형과 함수포인터를

인자로 받는다는 것이고 앞의 void와 젤 뒤의 int는 signal함수가

리턴하는 값이 int를 인자로 가지는 함수의 포인터라는것입니다.

복잡하게 보이지만 분석해보시면 간단할겁니다^^

10년후의 나와 인사하자!!

stoneshim의 이미지

system call을 man 해보면 ERRORS 항목에 EINTR 이 나오는 경우가 있습니다. 대표적인 예로 man 2 read 해보세요.

이게 바로 이 system call을 사용하는 경우 block이 될 수 있고(이게 책에서 표현하는 느린 시스템 호출입니다) 이때 signal이 발생하면 이 system call이 return하고(대부분 -1) errno가 EINTR로 setting된다는 의미입니다.

이런 경우가 발생할 수 있기 때문에 대부분의 느린 시스틈 호출을 사용하는 경우에 다음과 같이 코딩합니다.

int ret;
...
while(1) {
  ret = 특정systemcall();
  if( ret < 0 && errno == EINTR )
      continue;
}

man 해보았을 때 ERROS 항목에 EINTR이 있다면 대부분 위와 비슷한 방식으로 코딩해야 합니다.

우리 모두 리얼리스트가 되자. 그러나 가슴에 이룰 수 없는 꿈을 가지자

xfmulder의 이미지

프로그램을 하다보면 꼭 시그널처리에 대해 이해하고 넘어가야 합니다.
예를 들면 최소한 SIGSEGV 에 대해서는 처리해야 하겠지요.

signal (SIGSEGV, sig_catch) ;
signal (SIGTERM, sig_catch) ;

그런데 이렇게 시그널핸들러를 쓰게 되면
반드시 프로세스가 그 시그널을 만난다고 생각하시는게 맞습니다.

따라서 시스템콜에 대해 실패하고 나면 반드시 errno == EINTR 인지를 확인해야 합니다.

그런데 모든 경우에 다 체크할수는 없을것입니다.
예를들면

again:
mypid == getpid();
if (mypid<0 && errno == EINTR) {
    goto again ;
}

이런것까지 다 체크하실 필요는 없겠지요.

모두다 체크하지 않더라도 꼭 체크해야 할 시스템콜들은 블락되는 명령들입니다.
예를들면 read() 와 select() 와 msgrcv() 와 wait() 가 있습니다.
단, 비블럭킹 모드로 작동하는 경우에는 시그널만날 확률이 매우 낮습니다.
(비블럭킹모드 예 msgrcv(,,, IPC_NOWAIT) <--- 이런경우에는 메세지큐에서 읽을것이 없으면 곧바로 리턴하므로 시그널을 만나지 않을것임)

이런 명령들은 명령이 끝날때까지 블락된 상태로 계속 대기해야 하기 때문에 시그널을 꼭 만나게 됩니다.

내 자식들도 나처럼 !!

댓글 달기

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