공유 메모리 관련...

moonzoo의 이미지

공유 메모리 세그먼트에 접근할때

shmat를 사용하는데 .. 읽기 전용으로 접근시에..

예를 들어

 char * sptr = (char *)shmat(shmid, 0, SHM_RDONLY);

위와 같이 sptr을 얻어서 메모리 읽기가 가능합니다.

문제는 char * 이므로 값을 변경할때

strcpy , sprintf, memcpy 등을 이용해서 값을 변경하는데

이때...

READ ONLY 이므로 SIGBUS signal이 발생합니다..

문제는 위에 3개의 함수에 errno == EINTR 등의 처리 루틴을

사용할 수가 없다는데에 있습니다.
(sprintf는 errno가 정의되어 있고 EINTR도 있는데..
if( errno == EINTR)루틴으로 안나오고 계속 sprintf을 하면서
SIGBUS signal을 계속 발생시키더군요...)

=======================

요점은 readonly로 된 공유 메모리에 쓸려고 할때

단지 SIGBUS가 아닌

"메모리에 쓸수 없다" 메시지를 뿌리고 싶은 소망--; 입니다.

도움 부탁드립니다.

xjiwoox의 이미지

signal()이나 sigaction()으로 해당 시그널을 SIG_IGN처리해보세요.
소켓이나 파이프 사용할 때 읽는쪽의 연결이 끊어진 후에 write를 하면
SIGPIPE가 발생하는데, 이때 해당 시그널을 무시하면 write()류의 함수에서
ESPIPE errno가 발생하더군요.
sprintf()에서 같은 errno가 발생하는지 여부는 확실치 않지만 SIGBUS를
무시함으로서 시그널로 인해 프로세스가 종료되는 것을 막을 수 있구요..
SIG_IGN 대신 핸들러 함수를 등록해서 대신 메세지를 뿌려줄 수도 있겠죠.
(굳이 sprintf() 함수의 리턴코드와 errno를 조사해서 메세지를 뿌리고
싶으시다면 위의 방법대로 시그널 무시하시고 함수 리턴코드와 errno값을
체크해 보신 뒤, 그 결과대로 조건문을 수정하시면 되겠습니다.)

s(˘∼˘*)z,·´″"`°³о$ √(´∀`√)... (˘ヘ˘ㆀ)a

moonzoo의 이미지

답변 감사드립니다..

말씀하신 SIG_IGN은 해보았으나..

한번 무시한다 하더라도 그 루틴에서 탈출하지 못하고
( 그 루틴 => 예) sprintf(shmptr,"this is test");

계속 SIGBUS 를 발생시키네요..

write 등은 signal걸렸을때 errno 찍고 나오는데..

sprintf, strcpy, memcpy 등등은 탈출못하고

계속 반복되네요..

ohojang의 이미지

요즘 유닉스 시스템 프로그래밍을 한지 좀 오래되어서 한번 제

리눅스에다가 실행해 보고 싶은데 밤이 너무 늦어서 일단 저의

소견을 올립니다.

read, wirte 같은 경우는 이것은 시스템 콜이기 때문에 이함수를

호출할 경우는 제어가 커널로 넘어갔다고 봐야 됩니다. 그래서

관련된 시그널을 받으면 errno 를 세팅하고 다시 빠져 나올수 있습니다.

하지만 sprintf , memcpy 같은 경우는 이것은 C 라이브러리 함수이고

이것은 유저 모드에서 돌아갈 뿐입니다.

그렇기 때문에 errno 에 적절한 값을 주고 리턴하는 과정이 없다고

생각합니다.

굳이 이러한 기능이 꼭 필요하시다면,

이러한 라이브러리의 실행을 취소시킬 만한 일반적인 방법은 없기

때문에 sprintf, memcpy 등을 감싸는 함수를 만들어

보는것이 좋을 것 같습니다.

익명 사용자의 이미지

sighandler()
{
	signal(SIGBUS, SIG_IGN);
	printf("메모리에 쓸 수가 없어요!\n");
	...
	signal(SIGBUG, sighandler);
}

이렇게 하면 되지 않을까요?
shkwon81의 이미지

Quote:
문제는 위에 3개의 함수에 errno == EINTR 등의 처리 루틴을

사용할 수가 없다는데에 있습니다.
(sprintf는 errno가 정의되어 있고 EINTR도 있는데..
if( errno == EINTR)루틴으로 안나오고 계속 sprintf을 하면서
SIGBUS signal을 계속 발생시키더군요...)

실행 환경은 리눅스인가요? 리눅스에서는 signal() 함수를 사용하여 시그널 핸들러를 등록할 경우, 시그널에 의해 인터럽트된 시스템 콜(위에서는 write 겠지요)을 자동으로 재시작합니다. 그래서 그런 문제가 발생한 것 같은데요..

signal() 함수 대신 sigaction() 함수로 시그널 핸들러를 등록하되, flag 값 중에 SA_RESTART를 꺼(!!!) 놓아 보시길.. 그래도 계속해서 SIGBUS가 발생하는지요?

저도 결과가 궁금하네요.. 아니면 위에 분이 제시하신 것처럼 시그널 핸들러에서 직접 에러 메시지를 뿌려 주는 방법도 있을 거구요. 다음처럼 해 줘도 되겠죠.. (약간 문제의 소지는 있습니다만 ^^)

sighandler() 
{ 
   signal(SIGBUS, SIG_IGN);
   errno = EINVAL;
   signal(SIGBUG, sighandler); 
}

위와 같이 하면, read나 write의 error code와 동일한 에러를 내는 것과 같은 효과를 낼 수 있겠죠.. 예를 들어 write 시스템 콜은 read-only fd 로 쓰기를 시도하면 EINVAL을 세팅합니다.

댓글 달기

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