C/C++ 에서 이런게 안되나요?

thisrule의 이미지

프로그램의 특정 시점부터 stdout 출력을 다른 곳으로 redirection 하려 합니다.
이걸 구현하기 위해 pipe를 이용하여 보았습니다.

int fd[2];
fd[0] = 1;  // stdout의 file descriptor를 입력으로 설정
fd[1] = open( "/tmp/mylog", O_WRONLY );  // 출력을 위한 다른 descriptor
if( pipe( fd ) < 0 )
{
    perror( "pipe error: " );
    return;
}
printf( "this is a test\n" );

위와 같이 하면 마지막 printf 내용이 /tmp/mylog에 저장되어야 할 거 같은데 그렇게 되질 않네요?
pipe생성시 error도 발생하지 않았는데 왜 그럴까요?
저렇게 되질 않나요?

superkkt의 이미지

dup2 함수를 사용해서 /tmp/mylog의 fd를 stdout로 만드는게 더 편하지 않나요?

======================
BLOG : http://superkkt.com

정태영의 이미지

pipe 를 그렇게 쓰는게 아니기 때문에 그렇습니다 :)

원하시는 동작을 하려면 dup 등을 통해 stdout 등을 복사해놓고 close 로 stdout 을 닫은 다음에 출력을 리다이렉션 시키기 위한 파일을 열어야 합니다 :)

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

superkkt의 이미지

정태영 wrote:
원하시는 동작을 하려면 dup 등을 통해 stdout 등을 복사해놓고 close 로 stdout 을 닫은 다음에 출력을 리다이렉션 시키기 위한 파일을 열어야 합니다 :)

위 과정대로 하지않고 dup2를 사용해서 열린 파일의 fd를 바로 stdout로 만들어버리면 원하는 결과를 얻을 수 없나요?

======================
BLOG : http://superkkt.com

dotri의 이미지

되긴 됩니다만, 그러면 원래의 stdout 을 쓰고싶을때 복구할 방법이 없어지죠.

maximus의 이미지

약간 성격이 틀린 부분일수 있겠습니다만..
이건 어때요 ?

mylog 사이즈는 미리 알수 있으니 알맞게 사용하면 될듯 한데요.

char c;
fp=popen("cat /tmp/mylog","r");
while((c=getc(fp))!=EOF) printf("%c",c); //*ptr++=c;
fflush(fp);
pclose (fp);

=================================
:: how about a cup of tea ? ::
=================================

thisrule의 이미지

그렇군요. pipe를 그렇게 사용할 순 없군요...

그러면 이건 안되나요?
이미 열려진 socket이 있는데, stdout을 socket으로 연결하여 stdout으로 출력되는 것을 연결된 socket stream으로 내볼낼 순 없는지요.
그렇게 하면, printf()를 사용한 모든 내용이 socket을 통해 remote의 다른 process로 내보낼 수 있을거 같은데요.
그건 안될까요?

정태영의 이미지

thisrule wrote:
이미 열려진 socket이 있는데, stdout을 socket으로 연결하여 stdout으로 출력되는 것을 연결된 socket stream으로 내볼낼 순 없는지요.

dup2 로 socket descriptor 를 stdout 에 복사하면 되지 않을까요 ;)

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

thisrule의 이미지

정태영 wrote:
thisrule wrote:
이미 열려진 socket이 있는데, stdout을 socket으로 연결하여 stdout으로 출력되는 것을 연결된 socket stream으로 내볼낼 순 없는지요.

dup2 로 socket descriptor 를 stdout 에 복사하면 되지 않을까요 ;)


오! 그렇게 하니 되는듯 합니다. 좀 희망이 보이네요.
그런데 하나의 문제와 한가지 궁금증이 있습니다.

dup2로 socket descriptor를 stdout에 복사한 후, 아래와 같은 code가 있을때

write( 1, "new message", 11 );
printf( "new message\n" );

중에서 write()함수는 socket으로 전송되는 반면, printf() 함수는 stdout에도, socket으로도 출력되질 않습니다. 왜 그럴까요?

궁금한 사항은 dup2()의 return값도 file descriptor인데 그건 어디에 사용해야 하나요?

maximus의 이미지

DESCRIPTION
dup and dup2 create a copy of the file descriptor oldfd.

After successful return of dup or dup2, the old and new descriptors may be used interchangeably. They share locks, file
position pointers and flags; for example, if the file position is modified by using lseek on one of the descriptors, the
position is also changed for the other.

The two descriptors do not share the close-on-exec flag, however.

dup uses the lowest-numbered unused descriptor for the new descriptor.

dup2 makes newfd be the copy of oldfd, closing newfd first if necessary.

RETURN VALUE
dup and dup2 return the new descriptor, or -1 if an error occurred (in which case, errno is set appropriately).

ERRORS
EBADF oldfd isn't an open file descriptor, or newfd is out of the allowed range for file descriptors.

EMFILE The process already has the maximum number of file descriptors open and tried to open a new one.

EINTR The dup2 call was interrupted by a signal.

EBUSY (Linux only) This may be returned by dup2 during a race condition with open() and dup().

=================================
:: how about a cup of tea ? ::
=================================

thisrule의 이미지

maximus wrote:
DESCRIPTION
dup and dup2 create a copy of the file descriptor oldfd.

After successful return of dup or dup2, the old and new descriptors may be used interchangeably. They share locks, file
position pointers and flags; for example, if the file position is modified by using lseek on one of the descriptors, the
position is also changed for the other.

The two descriptors do not share the close-on-exec flag, however.

dup uses the lowest-numbered unused descriptor for the new descriptor.

dup2 makes newfd be the copy of oldfd, closing newfd first if necessary.

RETURN VALUE
dup and dup2 return the new descriptor, or -1 if an error occurred (in which case, errno is set appropriately).

ERRORS
EBADF oldfd isn't an open file descriptor, or newfd is out of the allowed range for file descriptors.

EMFILE The process already has the maximum number of file descriptors open and tried to open a new one.

EINTR The dup2 call was interrupted by a signal.

EBUSY (Linux only) This may be returned by dup2 during a race condition with open() and dup().


저도 man은 다 읽어보았습니다.
단지 영어가 짧아 다 이해되진 않지만 대충 그런거구나 해서 실험해 본겁니다.
문제는 write() 함수는 잘 되는데, 왜 printf() 함수는 잘 안되는가 하는 것입니다.[/b]
정태영의 이미지

thisrule wrote:
문제는 write() 함수는 잘 되는데, 왜 printf() 함수는 잘 안되는가 하는 것입니다.[/b]

buffered I/O 를 하기 때문에 아닐까요?

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

thisrule의 이미지

정태영 wrote:
thisrule wrote:
문제는 write() 함수는 잘 되는데, 왜 printf() 함수는 잘 안되는가 하는 것입니다.[/b]

buffered I/O 를 하기 때문에 아닐까요?


그렇군요.
setvbuf( stdout, NULL, _IONBF, 0 ); 을 한 후 하니 잘 됩니다.
도움 주신 모든 분들께 감사드립니다.

댓글 달기

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