天天看點

linux下線程之間pipe通信c++練習

 首先是用pipe在主線程和子線程通信,而且read是阻塞的

#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>

typedef struct __Thread
{
    pthread_t tid;                 //thread id
    int notifyReceiveFd;           //the receive side of pipe
    int notifySendFd;              //the send side pf pipe
} Thread;

Thread* m_thread;

void* work_thread(void* argc)
{
    Thread* param=(Thread*) argc;
    printf("childthread_id=%lu\n",param->tid);
    int contant=0;
    printf("childthread--read return %ld\n",read(param->notifyReceiveFd, &contant, sizeof(int)));
    printf("childthread--read from pipe %d\n", contant);

    sleep(5);
    contant=100;
    //printf("childthread--write return %ld\n", write(param->notifySendFd, &contant, sizeof(int)));

}

int main(int argc, char** argv)
{
    //build pipe between main-thread and child-thread
    m_thread = new Thread;
    int fds[2];
    if(pipe(fds))
    {
        perror("create pipe fds_1 error\n");
    }

    int fds_1[2];
    if(pipe(fds_1))
    {
        perror("create pipe fds_1 error\n");
    }

    m_thread->notifyReceiveFd=fds[0];
    m_thread->notifySendFd=fds_1[1];

    pthread_t id;


    pthread_create(&(m_thread->tid),NULL,work_thread,(void*)m_thread);
    printf("mainthread--childthread id is %lu\n",m_thread->tid);

    int contant = 1;

    printf("mainthread--write %d to pipe\n",contant);
    printf("mainthread--write return %ld\n", write(fds[1], &contant, sizeof(int)));

    //下面的read()函數會阻塞,因為沒有給fds_1管道寫入資料(把work_thread中注釋掉的write那行去掉注釋,則read()就可以讀到資料而不阻塞)
    printf("mainthread--read return %ld\n", read(fds_1[0], &contant, sizeof(int)));

    printf("mainthread--read from pipe %d\n", contant);
    pthread_join(m_thread->tid,NULL);
    close(fds[0]);
    close(fds[1]);
    close(fds_1[0]);
    close(fds_1[1]);
}
           

 上面的代碼會被阻塞,若要不阻塞運作,則要把檔案描述符設定為非阻塞的,則read會立即傳回(當管道沒有資料可讀時傳回-1)

fcntl(fds_1[0], F_SETFL, O_NONBLOCK);
    //在read前,用fcnl設定fds_1[0]為非阻塞的
    printf("mainthread--read return %ld\n", read(fds_1[0], &contant, sizeof(int)));
           

如要設定逾時,可以使用select或poll,下面代碼隻舉例select。更多相關知識可以參考這篇文章

#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>

typedef struct __Thread
{
    pthread_t tid;                 //thread id
    int notifyReceiveFd;           //the receive side of pipe
    int notifySendFd;              //the send side pf pipe
} Thread;

Thread* m_thread;

void* work_thread(void* argc)
{
    Thread* param=(Thread*) argc;
    printf("childthread_id=%lu\n",param->tid);
    int contant=0;
    printf("childthread--read return %ld\n",read(param->notifyReceiveFd, &contant, sizeof(int)));
    printf("childthread--read from pipe %d\n", contant);


    sleep(5);
    contant=100;
    //printf("childthread--write return %ld\n", write(param->notifySendFd, &contant, sizeof(int)));

}

int main(int argc, char** argv)
{
    //build pipe between main-thread and child-thread
    m_thread = new Thread;
    int fds[2];
    if(pipe(fds))
    {
        perror("create pipe fds_1 error\n");
    }

    int fds_1[2];
    if(pipe(fds_1))
    {
        perror("create pipe fds_1 error\n");
    }

    m_thread->notifyReceiveFd=fds[0];
    m_thread->notifySendFd=fds_1[1];

    pthread_t id;


    pthread_create(&(m_thread->tid),NULL,work_thread,(void*)m_thread);
    printf("mainthread--childthread id is %lu\n",m_thread->tid);

    int contant = 1;

    printf("mainthread--write %d to pipe\n",contant);
    printf("mainthread--write return %ld\n", write(fds[1], &contant, sizeof(int)));

    fd_set m_fds;
    FD_ZERO(&m_fds);
    FD_SET(fds_1[0], &m_fds);
    struct timeval t = {10, 0};
    select(fds_1[0] + 1, &m_fds, NULL, NULL, &t);
//若10後内fds_1[0]不可讀則停止阻塞,程式繼續往下走;如果把work_thread中的write那行去掉注釋,
//則注釋到write執行完畢,因為我write前sleep了5s,是以我這裡會阻塞5s,然後程式繼續往下走
    printf("mainthread--read return %ld\n", read(fds_1[0], &contant, sizeof(int)));

    printf("mainthread--read from pipe %d\n", contant);
    pthread_join(m_thread->tid,NULL);
    close(fds[0]);
    close(fds[1]);
    close(fds_1[0]);
    close(fds_1[1]);
}