select() 함수를 이용한 터미널 선택 출력

여리왕자의 이미지

리눅스에서 select 함수를 이용하여 현제 사용가능한 파일 디스크립터를 선택한후
선택된 파일디스크립터를 통하여 화면에 스트링을 출력하는 문제입니다...

기본적으로 터미널을 3개를 띄운 후에 1개의 창은 나머지 2개의 창을 모니터링 하고 있구...
나머지 두 창에서 스트링을 입력하면 모니터링 하고 있는 창에 스트링이 출력되게 해야하는데....

몇시간 동안 붙잡고 끙끙댄 결과... 두개의 터미널을 모두 인식은 하는것 같은데 제대로 출력은 안되네요... ㅜㅜ

뭐가 문제냐 하면요~~ ( 문제야 이곳 저곳 많겠지만... ㅡㅡ;;; ) 마우스로 새로운 터미널을 찍고
키보드로 문자가 입력되기 시작하면 [ read descriptor = 1 ] 이라는 메시지가 찍히게 해놓았습니다.
이 메시지가 찍히고 나서 스트링을 좌좌좍~ 입력화면 좌좌좍~ 모니터링 하고있는 터미널에 찍혀야 하는데... 저 메시지가 찍힌후 한 문자(char)만 찍히고 나서는 제어가 어딘가로 사라져 버리는것 같습니다.
딱 한문자만 찍히고는 안찍히네요... 또 옆에 모니터링 되고있는 다른창을 찍어서 입력하면 한문자만 입력이 되구요... 이런식으로 계속 1문자식은 입력이 가능합니다... ㅡㅡ;;;
아~~~~ 뭐가 문제인지 모르겠네요....

고수님들의 눈썰미가 필요합니다... 자~ 자~~~ 한번만 도와주세요~ ^^ㅋ...
내공 팍팍~~ 드립니다~~~ ㅡ.ㅡ;;;;;;

아! 파일도 따로 첨부합니다!!

// 헤더파일
#include <string.h>
#include <sys/time.h>
#include <fcntl.h>
#include <errno.h>
 
ssize_t r_read(int, void *, size_t );
ssize_t r_write(int, void *, size_t );
int readwrite(int, int );
int copy2files(int, int, int, int );

// 함수 라이브러리 파일
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>  //  PIPE_BUF 정의되어있는 헤더파일
#include <fcntl.h>
 
#define BLKSIZE PIPE_BUF
 
ssize_t r_read(int fd, void *buf, size_t size) {
   ssize_t retval;
 
   while (retval = read(fd, buf, size), retval == -1 && errno == EINTR) ;
   return retval;
}  
 
ssize_t r_write(int fd, void *buf, size_t size) {
   char *bufp;
   size_t bytestowrite;
   ssize_t byteswritten;
   size_t totalbytes;
 
   for (bufp = buf, bytestowrite = size, totalbytes = 0;
        bytestowrite > 0;
        bufp += byteswritten, bytestowrite -= byteswritten) {
      byteswritten = write(fd, bufp, bytestowrite);
      if ((byteswritten) == -1 && (errno != EINTR))
         return -1;
      if (byteswritten == -1)
         byteswritten = 0;
      totalbytes += byteswritten;
   }
   return totalbytes;
}
 
int readwrite(int fromfd, int tofd) {
   char buf[BLKSIZE];
   int bytesread;
 
   if ((bytesread = r_read(fromfd, buf, BLKSIZE)) == -1)
      return -1;
   if (bytesread == 0)
      return 0;
   if (r_write(tofd, buf, bytesread) == -1)
      return -1;
   return bytesread;
}
 
int copy2files(int fromfd1, int tofd1, int fromfd2, int tofd2) {
   int i;
   int bytesread;
   int maxfd;
   int num;
   fd_set readset;  
   int totalbytes = 0;
 
   if ((fromfd1 < 0) || (fromfd1 >= FD_SETSIZE) ||
       (tofd1 < 0) || (tofd1 >= FD_SETSIZE) ||
       (fromfd2 < 0) || (fromfd2 >= FD_SETSIZE) ||
       (tofd2 < 0) || (tofd2 >= FD_SETSIZE))
      return 0;
 
   maxfd = fromfd1;                     // find the biggest fd for select
   if (fromfd2 > maxfd)
      maxfd = fromfd2; 
 
   for ( i=0; i<3; i++ ) { 
      printf("i = %d\n", i);
      FD_ZERO(&readset);
      FD_SET(fromfd1, &readset);
      FD_SET(fromfd2, &readset);
 
      if (((num = select(maxfd+1, &readset, NULL, NULL, NULL)) == -1) &&
         (errno == EINTR)) 
         continue;
      if (num == -1) 
         return totalbytes;
      if (FD_ISSET(fromfd1, &readset)) {
         bytesread = readwrite(fromfd1, tofd1);
         if (bytesread <= 0)
            break;
         totalbytes += bytesread;
      }
      if (FD_ISSET(fromfd2, &readset)) {
         bytesread = readwrite(fromfd2, tofd2);
         if (bytesread <= 0) 
            break;
         totalbytes += bytesread;
      }
   }
   return totalbytes;
}

// 메인 파일  
#include <stdio.h>
#include <sys/select.h>
#include <sys/types.h>
#include "restart.h"
 
int main( void )
{
	int i=1;
	char buf[256];
	char buf2[256];
	fd_set readset;
	//struct timeval t;
 
	int maxfd, bytesread;
	int fd_read1, fd_read2;	
	int fd_write;
 
	fd_read1 = open("/dev/pts/6", O_RDONLY);   // 스트링을 받아들을 첫번째 터미널 디바이스 파일
	fd_read2 = open("/dev/pts/7", O_RDONLY);   // 스트링을 받아들일 두번째 터미널 디바이스 파일
 
	fd_write = open("/dev/pts/5", O_WRONLY);   // 스트링을 출력할 터미널 디바이스 파일 
 
	maxfd = fd_read1;
	if ( maxfd < fd_read2 ) maxfd = fd_read2;
	if ( maxfd < fd_write ) maxfd = fd_write;
	maxfd++;	
 
	//t.tv_sec = 20;
 
	while ( 1 ) {
		FD_ZERO( &readset );
 
		FD_SET( fd_read1, &readset );
		FD_SET( fd_read2, &readset );
 
		i = select( maxfd, &readset, NULL, NULL, NULL );
		printf("[ read descriptor = %d ]\n", i);	
 
		if ( FD_ISSET( fd_read1, &readset ) ) {
			bytesread = r_read( fd_read1, buf, 256 );
			write( fd_write, buf, bytesread );
		}
		else if ( FD_ISSET( fd_read2, &readset ) ) {
			bytesread = r_read( fd_read2, buf, 256 );
			write( fd_write, buf, bytesread );
		}
		else continue;
	}
 
	//copy2files( fd_read1, fd_write1, fd_read2, fd_write2 );
 
	//printf("fd_read1 = %d, fd_read2 = %d\n", fd_read1, fd_read2);
	//printf("fd_write1 = %d, fd_write2 = %d\n", fd_write1, fd_write2);	
	//printf("max = %d", maxfd);
 
	return 0;
}

소스는 위와 같습니다...
아!! 그리구 FD_ZERO 라던가 FD_SET, FD_ISSET, FD_CLR 등의 매크로들이 돌아가는 매커니즘도
좀 설명해주시면 감사하겠습니다... 수업 진도가 넘 빨리나가서 대강대강 모두 보고는 넘어가지만...
그래도 원리를 알고 넘어가면 재미(?) 있지 않겠습니까...
대강은 알것 같지만... 대강대강 주의는 아니라서.... ㅡㅡㅋ...

File attachments: 
첨부파일 크기
파일 플그램.tar17.5 KB

댓글 달기

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