/*
poll 阻塞的使用:

poll就是对描述符进行监听,和select类似,但是poll没有最大描述符的限制,并且poll的描述符使用之后不会被清空,而select每次使用之后都要重新设置.不过他俩作用是一样的,

进行阻塞操作.



通过调用poll之后,内核可以告诉我们是否可以读写操作.



pollfd结构体定义如下:


struct pollfd {


int fd;          // 文件描述符
short events;         // 等待的事件
short revents;       // 实际发生了的事件
} ; 


/*
  每一个pollfd结构体指定了一个被监视的文件描述符,可以传递多个结构体,指示poll()监视多个文件描述符。每个结构体的events域是监视该文件描述符的事件掩码,由用户来设置这个域。revents域是文件描述符的操作结果事件掩码,内核在调用返回时设置这个域。events域中请求的任何事件都可能在revents域中返回。合法的事件如下:


  POLLIN         有数据可读。


  POLLRDNORM       有普通数据可读。


  POLLRDBAND      有优先数据可读。


  POLLPRI         有紧迫数据可读。


  POLLOUT            写数据不会导致阻塞。


  POLLWRNORM       写普通数据不会导致阻塞。


  POLLWRBAND        写优先数据不会导致阻塞。


  POLLMSGSIGPOLL     消息可用。


  此外,revents域中还可能返回下列事件:
  POLLER     指定的文件描述符发生错误。


  POLLHUP   指定的文件描述符挂起事件。


  POLLNVAL  指定的文件描述符非法。


这些事件在events域中无意义,因为它们在合适的时候总是会从revents中返回。


*/


// linux14.04编译环境
// g++ poll.cpp -lpthread
// ./a.out
// 代码如下:




#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <poll.h>
#include <pthread.h>




int m_pipe[2];


pthread_t thread[2];
pthread_mutex_t mut;


void* interrupt(void *)
{
while(1) {


    usleep(1000000);
    printf("interrupt\n");
    static const char dummy = 0;
    int n;
    do {
        n = write(m_pipe[1], &dummy, 1);
    } while ((n < 0) && (errno == EINTR));


    printf("thread quit!\n");
    return 0;// 如果没有return,则会一直循环,知道进程结束.
    if (n < 0) {
        printf("Error writing to pipe (%s)", strerror(n));
    }
}
}


int main()
{


    int ret = pipe(m_pipe);
    printf("pipe %d %d \n", m_pipe[0], m_pipe[1]);
    
    if (ret != 0) {
        m_pipe[0] = -1;
        m_pipe[1] = -1;
        printf("log create pipe failed");
        return -1;
    }
    
    struct pollfd readFds[2] = {};
    // readFds[0].fd = m_dataFd;
    // readFds[0].events = POLLIN;
    readFds[1].fd = m_pipe[0];
    readFds[1].events = POLLIN;
    
    int temp;
    memset(&thread, 0, sizeof(thread));        
/*创建线程*/
if((temp = pthread_create(&thread[0], NULL, interrupt, NULL)) != 0)
printf("线程1创建失败!\n");
    
    
   while(1) {
   
       int ret = poll(readFds, 2, 100000);
       if (0 > ret) {
           printf("poll ret < 0, ret = %d", ret);
           return -1;
       }
       
       if (readFds[1].revents & POLLIN) {
        printf("interrupt by pipe\n");
        char c;
        int n;
        do {
            n = read(m_pipe[0], &c, 1);
            printf("after read ret:%d, read value %d\n", n, c);
        } while (n < 0 && errno == EINTR);


        if (n < 0) {
            printf("Error reading from pipe (%s)", strerror(errno));
        }
        printf("main quit thread\n");
        return -1; //这里如果不return,主线程则不会退出,要注意子线程会不会退出.
        // break; //用break,则子线程不会退出,如果子线程没有return操作,则会一直循环.
       }
     
   }
    
usleep(10000000);
printf("11111111111111111111");
    return 0;
}
Logo

更多推荐