首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

linux 管道 线程同步,该如何处理

2012-12-23 
linux 管道线程同步各位,最近想使用管道来实现线程同步,出现一个问题,百思不得其解,望各位大侠指点一二...

linux 管道 线程同步
各位,最近想使用管道来实现线程同步,出现一个问题,百思不得其解,望各位大侠指点一二...
先贴上代码:


#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>



int pip[] = {-1, -1};


void sleep_select(int i)
{
    struct timeval timeout;
    timeout.tv_sec = i;
    timeout.tv_usec = 0;
    select(0, NULL, NULL, NULL, &timeout);
}

static void *threadFunction(void* userdata)
{
    char data[5] = {0};
    fd_set fds;
    struct timeval timeout = {1,0};
    int ret;

    FD_ZERO(&fds);
    FD_SET(pip[0], &fds);

   printf("p0: %d\n", pip[0]);
   printf("p1: %d\n", pip[1]);

    while (1)
    {
        ret = select(pip[0] + 1, &fds, NULL, NULL, &timeout);
        if (ret < 0)
        {
            printf("select error\n");
            break;
        }
        else if (ret == 0)
        {
            //printf("no fd ready\n");
            continue;
        }
        else 
        {
            if (FD_ISSET(pip[0], &fds) > 0)
            {
                read(pip[0], data, 5);
                printf("data: %s\n", data);
            }
        }
    }
    
}

void *mysignal() 
{
    printf("signal\n");
    char data[] = "data";
    while (1)
    {
        sleep_select(2);
        //printf("sowelflsdfsldfsdlfsdl\n");
        write(pip[1], data, 5);
    }
}

int main(int argc, char* argv[])
{
   char data[] = "data"; 
   pthread_t id;

   if (pipe(pip)) {
       printf("pipe error\n");
       exit(-1);


   }
   printf("p0: %d\n", pip[0]);
   printf("p1: %d\n", pip[1]);

   if (pthread_create(&id, NULL, threadFunction, NULL))
   {
       printf("create thread error\n");
       exit(-1);
   }
   printf("pthread id = %u\n", id);
   pthread_create(&id, NULL, mysignal, NULL);
   //signal(SIGUSR1, mysignal);


   while (1)
   {
       sleep_select(2);
       //sleep(2);
       //write(pip[1], data, 5);
   }

   pthread_join(id, NULL);
}



    这个程序中,主线程创建两个线程,一个线程向管道的写端写入数据,另一个线程监听管道的读端,当如果有数据到来时,读线程从管道中读出数据并打印。。


问题来了: 首先当我在写线程中,不用sleep()函数时,读端能监听到管道符的变化,当我用上sleep函数时,读端就监听不到管道符的变化了,我想知道这是为什么。。。。sleep()函数会影响管道符吗。。。。。
[最优解释]
哦,shit,需要把timeout的赋值移到while内!

#include <unistd.h>
#include <sys/time.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
//#include <fcntl.h>



int pip[2] = {-1, -1};


void sleep_select(int i)
{
    struct timeval timeout;
    timeout.tv_sec = i;
    timeout.tv_usec = 0;
    select(0, NULL, NULL, NULL, &timeout);
}

static void *threadFunction(void* userdata)
{
    char data[6] = {0};
    fd_set fds;
    struct timeval timeout;

    int ret;

    FD_ZERO(&fds);
    FD_SET(pip[0], &fds);

    printf("p0: %d\n", pip[0]);
    printf("p1: %d\n", pip[1]);

    int counter = 0;

    while (1)
    {
        timeout.tv_sec = 5;
        timeout.tv_usec = 0;
        //FD_ZERO(&fds);
        FD_SET(pip[0], &fds);

        ret = select(pip[0]+1, &fds, NULL, NULL, &timeout);
        if (ret == -1)
        {
            printf("select error\n");
            break;
        }
        else if (ret > 0)
        {
            if (FD_ISSET(pip[0], &fds))
            {


                read(pip[0], data, 5);
                printf("data: %s\n", data);
                printf("%s: %d, [%s]\n", __FUNCTION__, counter++, strerror(errno));
            }
        }
        else
        {
            printf("no fd ready\n");
        }
    }

    return NULL;

}

void *mysignal()
{
    printf("signal\n");
    char data[] = "data";
    int counter = 0;
    while (1)
    {
        sleep_select(2);
        //sleep(2);
        //printf("sowelflsdfsldfsdlfsdl\n");
        write(pip[1], data, 5);
        printf("time:%lu,%s: %d, [%s]\n", time(NULL), __FUNCTION__, counter++, strerror(errno));
    }
}

int main(int argc, char* argv[])
{
    pthread_t id;

    if (pipe(pip))
    {
        printf("pipe error\n");
        exit(-1);
    }
    printf("p0: %d\n", pip[0]);
    printf("p1: %d\n", pip[1]);

    //fcntl(pip[0], F_SETFL, fcntl(pip[0], F_GETFL, 0) 
[其他解释]
请仔细看select的说明,select会修改timeout值的。
[其他解释]
应该是write端sleep的时候,read端的select认为没有writer了,所以立即返回0了。
[其他解释]

引用:
应该是write端sleep的时候,read端的select认为没有writer了,所以立即返回0了。

我最开始也是这样觉得,可是当用sleep后,read端的select是一直返回0,即便是当写端已经写入数据后,读端还是会返回0.这个sleep到底影响了一些什么东西。。。
[其他解释]
sleep()/select()都会造成进程里所有的线程休眠,所以你的mysignal线程里的sleep会影响到threadFunction的select,select会发现每次都超时了

threadFunction--select sleep 1秒
mysignal sleep 2秒(threadFunction线程一样会受影响多休眠2秒)
threadFunction-select发现已经是3秒超时了,所以返回0

你应该用pthread_cond_wait在mysignal线程里对线程休眠



[其他解释]
引用:
sleep()/select()都会造成进程里所有的线程休眠,所以你的mysignal线程里的sleep会影响到threadFunction的select,select会发现每次都超时了

threadFunction--select sleep 1秒
mysignal sleep 2秒(threadFunction线程一样会受影响多休眠2秒)
threadFun……


你好,我开始试过,在主线程中select/sleep都不会造成子线程休眠,在线程中的休眠也是独立的,好像不会影响到其他的线程的
------其他解决方案--------------------


我发现两个问题,一是  struct timeval timeout = {1,0}; 这行代码不对,二是,把这行代码修改对之后,超时超时还是不起作用,如果设置无限阻塞,则可以达到预期效果。
就是说,把timeout正确初始化之后,设置的超时不起作用,导致狂打 "no fd ready\n"
[其他解释]
 O_NONBLOCK);
    //fcntl(pip[1], F_SETFL, fcntl(pip[1], F_GETFL, 0) 
[其他解释]
 O_NONBLOCK);

    if (pthread_create(&id, NULL, threadFunction, NULL))
    {
        printf("create thread error\n");
        exit(-1);
    }
    printf("pthread id = %lu\n", id);
    pthread_create(&id, NULL, mysignal, NULL);
    //signal(SIGUSR1, mysignal);


    while (1)
    {
        sleep_select(2);
        //sleep(2);
        //write(pip[1], data, 5);
    }

    pthread_join(id, NULL);
}


[其他解释]
heartlesstoanyone,高手,正解,select的实现不太合理。

热点排行