c - 系统调用 read 和 write 的行为如何以及为什么线程无法工作?

标签 c linux operating-system

fifo.3源码:

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

    #define FIFO_NAME "/tmp/my_fifo"
    #define BUFFER_SIZE PIPE_BUF   //4096
    #define TEN_MEG (1024 * 1024 * 1) 


void* thread_tick(void* arg)  
{
    int count =0;
   while(count < 4){
    printf("hello, world!\n");
    sleep(1);
    count++;
   }
}

void* thread_write(void* arg)
{
    int pipe_fd;
    int res;
    int bytes_sent = 0;
    char buffer[BUFFER_SIZE ];
    int count=0;    

    if (access(FIFO_NAME, F_OK) == -1) {
        res = mkfifo(FIFO_NAME, 0777);
        if (res != 0) {
            fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME);
            exit(EXIT_FAILURE);
        }
    }
     while(count < 10){
    printf("write: Process %d opening FIFO O_WRONLY\n", getpid());
    pipe_fd = open(FIFO_NAME, O_WRONLY);
    printf("write: Process %d result %d \n", getpid(), pipe_fd);

    if (pipe_fd != -1) {
        while(bytes_sent < TEN_MEG) {
            res = write(pipe_fd, buffer, BUFFER_SIZE);
            if (res == -1) {
                fprintf(stderr, "Write error on pipe\n");
                exit(EXIT_FAILURE);
            }
            bytes_sent += res;
        }
        (void)close(pipe_fd);
    }
    else {
        exit(EXIT_FAILURE);
    }

    printf("write: Process %d finished , count =%d\n", getpid(),count);
    count++;
  }
}


void CreateThread(void* (*start_routine)(void*), void* arg,int stacksize, int priority)
{
    pthread_t app_thread;
    pthread_attr_t thread_attr;
    int res;

    int max_priority;
        int min_priority;
        struct sched_param scheduling_value;

    res = pthread_attr_init(&thread_attr);
    if (res != 0) {
        perror("Attribute creation failed\n");
        exit(EXIT_FAILURE);
    }
         res = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
    if (res != 0) {
        perror("Setting detached attribute failed");
        exit(EXIT_FAILURE);
    }
    res = pthread_attr_setstacksize(&thread_attr, stacksize); 
    if (res != 0) {
        perror("Set stack size failed\n");
        exit(EXIT_FAILURE);
    }

    res = pthread_attr_setschedpolicy(&thread_attr, SCHED_RR); 
    if (res != 0) {
        perror("Setting schedpolicy failed");
        exit(EXIT_FAILURE);
    }

    max_priority = sched_get_priority_max(SCHED_RR);
    min_priority = sched_get_priority_min(SCHED_RR);
    scheduling_value.sched_priority = priority;
    res = pthread_attr_setschedparam(&thread_attr, &scheduling_value);
    if (res != 0) {
        perror("Setting schedpolicy failed");
        exit(EXIT_FAILURE);
    }

    res = pthread_create(&app_thread, &thread_attr, (*start_routine), arg);
    if(res != 0){
        perror("Thread creation failed\n");
        exit(EXIT_FAILURE);
        }
    pthread_attr_destroy(&thread_attr);

    //res = pthread_join(app_thread ,0 );
    //return app_thread;
}

int main()
{
     CreateThread(thread_write, 0, 50000, 99);
     CreateThread(thread_tick, 0, 50000, 98);
    // pthread_join(w,0 );
    // pthread_join(t ,0 );
    return 0;
}

fifo.4 源码:

    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <fcntl.h>
    #include <limits.h>
    #include <sys/types.h>
    #include <sys/stat.h>

    #define FIFO_NAME "/tmp/my_fifo"
    #define BUFFER_SIZE PIPE_BUF  //4096

int main()
{
    int pipe_fd;
    int res;
    char buffer[BUFFER_SIZE ];
    int bytes_read = 0;
    int count = 0;

    memset(buffer, '\0', sizeof(buffer));

    while(count < 10){
    printf("read: Process %d opening FIFO O_RDONLY\n", getpid());
    pipe_fd = open(FIFO_NAME, O_RDONLY);
    printf("read: Process %d result %d\n", getpid(), pipe_fd);

    if (pipe_fd != -1) {
        do {
            res = read(pipe_fd, buffer, BUFFER_SIZE);
            bytes_read += res;
        } while (res > 0);
        (void)close(pipe_fd);
    }
    else {
        exit(EXIT_FAILURE);
    }

    printf("read: Process %d finished, %d bytes read , count =%d\n", getpid(), bytes_read,count);
    count++;
  }
   return 0;
}

第一次在Stack overflow上贴代码,所以比较乱。 以上是两段C源代码。 fifo3.c有两个thread,thread_write是写数据到named fifo。 fifo4.c是从命名的fifo中读取数据。

我的问题:

1) 当 write() 将数据写入 fifo 时,read(pipe_fd, buffer, BUFFER_SIZE) 的行为如何?如果read()读不到数据,SHOULD not read() return 0 and exit,为什么read()要等write()写完数据???当然,当 read() 正在读取时 write() 的行为如何?

2) 在 fifo3.c 中,我创建了两个线程,当我创建它们分离时,程序无法运行! 但是可以joinable,可以正常运行!!不知道为什么! 理论上,它们都可以正常工作。

最佳答案

问题 1 的答案:

如果读取不能读取数据,它将“阻塞”直到数据到达,这称为阻塞模式读取。在阻塞模式读取的情况下,读取调用将阻塞直到数据到达。如果您希望将其更改为非阻塞模式,则可以使用 fcntl 功能(如果支持)。

对于其他查询,您最好通过手册页阅读它,因为很难得到简明的答案。

问题 2 的答案:

当您创建分离的线程时,这意味着创建的线程未绑定(bind)到创建它的父线程。因此,如果父线程完成其工作,它就会退出。如果父线程恰好是主线程,那么当它退出时,进程也会退出,导致程序无法运行。

关于c - 系统调用 read 和 write 的行为如何以及为什么线程无法工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9645329/

相关文章:

linux - Ghostscript 输出空白 pdf

linux - 桥接模式下的docker网络

python - 如何重命名子目录中的图像?

c - C 中长输入/输出的问题

c - C 编译器如何处理枚举?

c - 如何在C中分割随机数并在不使用数组的情况下获得每个数字的频率计数?

c - 自动微分Matlab Coder生成的C代码

linux -/dev/tcp 在 LINUX 中不存在

java - 根据使用的操作系统在 Swing 中加载图像图标

c - cga_putc中0x0700的作用是什么?