select는 특정 이벤트가 발생하면 running을 하지만 

poll은 계속해서 주기적으로 돌면서 이벤트를 체크한다. 


int poll(struct pollfd *fds, nfds_t nfds, int timeout);


1인자값 : 이벤트 등록 변수

2인자값 : 체크할 pollfd의 개수

3인자값 : time out 시간 


만약에 poll(0, 0, 1000); 이렇게 하면 

sleep(1); 과 같이 1초 delay를 줄 수 있다. 


출처: http://forum.falinux.com/zbxe/?document_srl=405838

위의 페이지에 따르면


POLL함수는 확인하고 싶은 여러가지 이벤트를 미리 등록해놓고 그 이벤트들이 발생했는지

확인할 수 있는 편리한 방법을 제공한다.

POLL 함수의 PHASE는 5단계로 다음과 같다. 


PHASE 1 : 주기적으로  check할 이벤트 등록

PHASE 2 : poll() 함수를 호출한다. 

PHASE 3 : 이벤트가 발생하면 poll()함수 호출 후에 바로 return.

PHASE 4 : 이벤트가 발생하지 않으면, 이벤트 발생할 때까지 time-out 시간 만큼 기다린다. 

PHASE 5 : 이벤트가 발생하면 해당 이벤트 배열 아이템의 값이 바뀌는데 이 값을 가지고 어느 이벤트가 발생했는지 알 수 있다. 


< 서버쪽 예제> ... 클라이언트가 자꾸 제대로 안된다.. OTL..

코드출처 : http://stackoverflow.com/questions/448331/my-simple-poll-example-only-partially-works

-----------------------------------------------


#include 
#include 
#include 
#include 
#include "sys/time.h"
#include "sys/types.h"
#include 
#include 
#include "sys/socket.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include 

#define PORT 29900 
#define MAX_CONN 10
#define SECOND 1000
#define TIMEOUT (30 * SECOND)

static int listen_socket();

int main(int argc, char **argv)
{
    struct pollfd **my_fds;                  //array of pollfd structures for poll()
    struct pollfd *curr, *new_conn;          //so I can loop through
    int num_fds;                             //count of how many are being used
    int i, j;                                //for loops
    char buff[255], buff2[255];              //for sending and recieving text
    struct sockaddr_in my_addr, their_addr;  // my address information
    socklen_t sin_size;
    int buff_sz;                             //size of data recieved

    printf("App Started\n");

    //allocate space for 10 
    my_fds = (struct pollfd**)calloc( MAX_CONN, sizeof(struct pollfd*));

    //set all the pointers to NULL
    for (i = 0; i < MAX_CONN; i++)
        *(my_fds + i) = NULL;

    //I call listen_socket() which creates a socket to listen to
    //this is anchored into my_fds array at element 0.
    curr = (struct pollfd*) calloc (1, sizeof(struct pollfd));
    curr->fd = listen_socket();
    curr->events = POLLIN;
    curr->revents = 0;

    *my_fds = curr;

    printf("Listening socket fd locked always at position zero in array: %d\n", curr->fd);

    //num_fds, the count of items in the array is set to 1
    //because the listen socket is already present
    num_fds = 1;

    //This is the main loop.
    //While (true)
    //  set all struct pollfd items revents to 0
    //  call poll
   //  loop through, see if there is data to read
    //  read the data
    //  loop through all sockets (except the listen_socket()) and send the data.
    while (1)
    {
        //reset all event flag
        for (i = 1; i < num_fds; i++)
        {
            curr = *(my_fds + i);
            curr->events = POLLIN | POLLPRI;
            printf("%i: fd %i\n", i, curr->fd);
            curr->revents = 0;
            send(curr->fd, "Enter some text:\n", 18, 0);
        }

        //put all this into poll and wait for something magical to happen
        printf("calling poll (%d sockets)\n", num_fds);
        if (poll(*my_fds, num_fds, TIMEOUT) == -1)
        {
            perror("poll");
            exit(0);
        }

        printf("poll returned!\n");

        //First item is the accepting socket....check it independently of the rest!
        curr = *my_fds;
        if (curr->revents != 0)
        {
            printf("We have a new connection.\nAccept goes here...\n");

            //Accept the connection
            sin_size = sizeof their_addr;
            new_conn = (struct pollfd*) calloc(1, sizeof(struct pollfd));
            new_conn->fd = accept(curr->fd, (struct sockaddr *)&their_addr, &sin_size);
            new_conn->events = POLLIN;
            new_conn->revents = 0;

            printf("Connection from %s\n", inet_ntoa(their_addr.sin_addr));
            sprintf(buff, "Your %i\n", num_fds);
            send(new_conn->fd, buff, 255, 0);

            //Add it to the poll call
            *(my_fds + num_fds) = new_conn;
            num_fds++;

        }
        else
        {
            //skip first one, we know that's the accepting socket (handled above).
            for (i = 1; i < num_fds; i++)
            {
                curr = *(my_fds + i);
                if (curr->revents != 0)
                {
                    buff_sz = recv(curr->fd, &buff, 255, 0);
                    buff[buff_sz] = '\0';
                    printf("Recieved: %s", buff);

                    //send the message to everyone else
                    for (j = 1; j < num_fds; j++)
                    {
                        printf("i = %i, j = %i\n", i, j);
                        if (j != i)
                        {
                            new_conn = *(my_fds + j);
                            sprintf(buff2, "%i sent you %i: %s", i, j, buff);
                            send(new_conn->fd, buff2, strlen(buff2) + 1, 0);
                        }
                    }
                }
            }
        }
    }

    printf("App Ended\n");
}

static int listen_socket()
{
    struct sockaddr_in a;
    int s;
    int yes;

    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket");
        return -1;
    }
    yes = 1;
    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
                (char *) &yes, sizeof(yes)) < 0) {
        perror("setsockopt");
        close(s);
        return -1;
    }
    memset(&a, 0, sizeof(a));
    a.sin_port = htons(PORT);
    a.sin_family = AF_INET;
    if (bind(s, (struct sockaddr *) &a, sizeof(a)) < 0) {
        perror("bind");
        close(s);
        return -1;
    }
    printf("Accepting connections on port %d\n", PORT);
    listen(s, 10);
    return s;
}


-----------------------------------------------


도무지 이해가 안가서 일부분만 떼어왔다.

http://forum.falinux.com/zbxe/?document_srl=405838

struct pollfd poll_events; // 체크할 event 정보를 갖는 struct

poll() 사용하기 위한 변수를 선언.
poll_events
에는 감시 대상인 디스크립터와 어떤 event 감시할지 결정해서 bit 값으로 지정.

int poll_state;

poll() 수행한 결과값. 아래와 같은 반환값.

 

poll() 수행 반환

 

반환

설명

음수

반환 값이 음수라면 치명적인 에러가 발생한 것입니다. 한번 이렇게 음수로 에러가 발생하면 이후 계속 음수값이 날라 옵니다. 거의 대부분 프로그램을 다시 실행해야 됩니다. 반드시 체크해야 겠지요.

0

지정한 대기시간, time-out 지나도록 발생한 event 없습니다.

양수

event 발생했습니다.

 

poll_events.fd = fd;

감시 대상인 디스크립터를 지정.

poll_events.events = POLLIN | POLLERR; // 수신된 자료가 있는지, 에러가 있는지

체크하고 싶은 event 대해 비트값으로 설정하여 지정.

poll_events.revents = 0;

revents 0 으로 초기화.

poll_state = poll(                               // poll() 호출하여 event 발생 여부 확인    
                  (
struct pollfd*)&poll_events, // event 등록 변수
                                             1,  //
체크할 pollfd 개수
                                          1000   // time out
시간
                );

체크할 event 정보를 넘겨 주고, 1 체크할 pollfd 개수.

예제에는 감시하는 디스크립터가 개이지만 프로그램에 따라서는 여러 개의 디스크립터를 관리할 경우가 많음.

 

관리할 디스크립터가 많을 , 각각을 변수로 처리하는 보다 배열로 처리하는 것이 편리.

이래서 poll() 편리.

poll() 변수 하나 외에도 배열을 받을 있으며,

한번의 호출로 모든 event 발생 여부를 확인할 있어 매우 편리.

 

1000 time-out 시간으로 발생한 event 없을 경우

poll() event 발생할 까지 time-out 시간 동안 대기.

 

if ( 0 < poll_state)

poll() 함수 결과가 양수라면 event 발생.

if ( poll_events.revents & POLLIN)

발생한 event 중에 POLLIN 있는 지를 확인.

POLLIN 해당되는 bit 1 세트되어 있다면 POLLIN으로 AND 값은 0 아닐 .

이렇게 비트값을 확인하여 event 발생 여부를 확인.

cnt = read( fd, buf, 1024);

write( fd, buf, cnt);

자료 수신 event 발생했으므로 fd로부터 자료 값을 읽어 들이고,

예제 테스트를 위해 다시 자료를 전송.

 

 

'Language > C' 카테고리의 다른 글

writev 함수 예제  (0) 2012.07.31
readv 함수 예제  (0) 2012.07.30
poll 함수 예제  (0) 2012.07.26
GCC 컴파일러 에러 메세지 리스트(Error Message List)  (0) 2012.07.24
select 함수 예제  (0) 2012.07.23
Unix Domain Socket 예제  (0) 2012.07.23

pipe()

- 하나의 파이프 및 파이프에 대한 두 개의 파일 디스크립터가 생성

- 하나의 파이프를 프로세스들이 공유

#include "sys/types.h"
#include 
#include 
#include 
#include 

#define MAXLINE 4096 /* max line length */ 

/* err_sys("") --> return(1) */

int main(void)
{
    int n, fd[2];
    pid_t pid;
    char line[MAXLINE];

    if (pipe(fd) < 0) {
        printf("pipe error \n");
        return(-1);
        /* err_sys("pipe error"); */
    }

    if ( (pid = fork()) < 0) {
        printf("fork error \n");
        return(-2);
        /* err_sys("fork error"); */

    } else if (pid > 0) { /* parent */

        close(fd[0]);
        write(fd[1], "Hello world\n", 12);

    } else { /* child */
        close(fd[1]);
        n = read(fd[0], line, MAXLINE);
        write(STDOUT_FILENO, line, n);
    }

    return(0);
}
/* The end of function */

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

파이브열고

포크로 자식 프로세스 만들어다가

read시키는데

이떄, 부모프로세스는 write으로 파이프의 내용을 읽어온다.

결국 위의 코드의 결과는

printf("%s\n", "Hello world");

와 동일하게 나옴. write함수에서 fd들어갈곳에 STDOUT_FILENO플래그를

넣었으니깐.

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

pipe() 함수는 파일 디스크립터 쌍을 생성하네, 2개 생성하는데.

filedes[2] => filedes[0] Read, filedes[1] Write. 용도로 만든다.

사용법
#include <unistd.h>

int pipe(int filedes[2]);

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

fork()함수는 Child process 생성하는 기본적인 멀티 프로세싱 함수

사용법
#include <unistd.h>

pid_t fork(void);

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

close()함수는 pipe로 열린 descriptor 닫아버리는 함수

SYNOPSIS
#include <unistd.h>

int close(int fd);

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


출처

1. advanced programming in the unix environment

 2. http://gatolu.tistory.com/entry/%ED%8C%8C%EC%9D%B4%ED%94%84-%ED%95%A8%EC%88%98 

'Language > C' 카테고리의 다른 글

mkfifo 함수 예제  (0) 2012.07.06
popen 함수 pclose 함수 예제  (0) 2012.07.06
pipe 함수 예제  (0) 2012.07.06
다차원 배열을 1차원 배열로 변경하고자 할 때  (0) 2011.08.11
C언어 - 스트림(Stream)이란?  (0) 2011.08.11
리눅스 시스템 프로그래밍 8장 IPC  (0) 2011.08.11

+ Recent posts