首先是用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]);
}