c/c++ 阻塞和非阻塞,fcntl應用


調用open函數時,可以指定打開的文件描述符是以阻塞方式還是以非阻塞方式。
阻塞概念:read函數在讀設備或者管道,或者socket的時候,默認是阻塞的,也就是說,對方如果沒有發送數據過來,則read函數就會一直等待數據過來,從代碼的角度來說,就是read函數后面的代碼不會被執行。
非阻塞概念:read函數在讀設備或者管道,或者socket的時候,對方如果沒有發送數據過來,read函數也會立即返回,從代碼的角度來說,就是read函數后面的代碼會馬上被執行。

  • 非阻塞方式打開:

    int fd = open("/dev/tty", O_RDWR|O_NONBLOCK);
    
  • 阻塞方式打開:

    int fd = open("/dev/tty", O_RDWR);
    

標准輸入輸出和錯誤,實際使用的文件是:/dev/tty,所以下面的例子用這個文件演示。
當用非阻塞的時候,如果沒有read到,函數不會等待,會立即返回,返回值是【-1】,這時errno的值為【11】,用perror打印出來的信息是【Resource temporarily unavailable】
例子:

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

int main(int argc, char* argv[]){
  int fd = open("/dev/tty", O_RDWR|O_NONBLOCK);
 
  char buf[256];
  while(1){
    int ret = read(fd, buf, sizeof buf);
    if(ret < 0){
      perror("read:");
      printf("ret :%d\n", ret);
    }
    printf("buf is:%s", buf);
    printf("haha\n");
  }
}

除了使用【O_NONBLOCK】外,還可以使用fcntl函數,原型如下:

#include <unistd.h>
#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* arg */ );

F_GETFD (void)
   Return  (as  the function result) the file descriptor flags; arg
   is ignored.
F_SETFD (int)
   Set the file descriptor flags to the value specified by arg.

例子:

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

int main(int argc, char* argv[]){
  int fd = open("/dev/tty", O_RDWR);

  //先取得fd的flag
  int flags = fcntl(fd, F_GETFL);
  //再在原來fd的flag的基礎上,設置上O_NONBLOCK
  flags |= O_NONBLOCK;
  //讓新的flag生效
  fcntl(fd, F_SETFL, flags);
  
  char buf[256];
  while(1){
    int ret = read(fd, buf, sizeof buf);
    if(ret < 0){
      perror("read:");
      printf("ret :%d\n", ret);
    }
    printf("buf is:%s", buf);
    printf("haha\n");
    sleep(1);
  }
}

c/c++ 學習互助QQ群:877684253

本人微信:xiaoshitou5854


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM