zoukankan      html  css  js  c++  java
  • fcntl函数用法——操纵文件描述符状态

    fcntl函数:操纵文件描述符,改变已经打开的文件的属性
    int fcntl(int fd, int cmd, ... //arg  );
    cmd选项:
    一、复制文件描述符:F_DUPFD
    二、更改设置文件描述标志:F_GETFD 、F_SETFD  文件描述符标志,是体现进程的文件描述符的状态.
    当前只定义了一个文件描述符标志FD_CLOEXEC。
       0: exec时不关闭已经打开的文件描述符
       1: exec时关闭已经打开的文件描述符

    三、获取或者设置文件状态标识:F_GETFL、 F_SETFL(读写追加阻塞等等)
        文件状态标签中的标志可分为三类:访问方式、打开时标志和I/O操作方式。
     1. 访问方式 访问方式指明允许文件描述字用于读、写或两者兼之,包括O_RDONLY、O_WRONLY和O_RDWR。
    这些访问方式在文件被打开时选定,之后便不能再改变。
     2、打开时标志指明打开文件时影响open()行为的一些选项。这些选项一旦文件打开就不保留,
    但有一个例外是O_NONBLOCK,因为O_NONBLOCK同时也是一个I/O操作方式,故此标志被保留例如:O_CREAT
     3、I/O操作方式:I/O操作方式影响使用文件描述字进行输入输出操作的工作方式。这些标志由open()设置,
    之后可以用fcntl()获取和改变。O_APPEND、O_NONBLOCK、O_SYNC等
    四、设置获取文件锁:F_GETLK、F_SETLK,F_SETLKW

     1 #include<unistd.h>
     2 #include<sys/types.h>
     3 #include<sys/stat.h>
     4 #include<fcntl.h>
     5 #include<stdlib.h>
     6 #include<stdio.h>
     7 #include<errno.h>
     8 #include<string.h>
     9 #define ERR_EXIT(m)
    10     do
    11     {
    12         perror(m);
    13         exit(EXIT_FAILURE);
    14     }while(0)  //宏要求一条语句
    15 void set_flags(int fd,int flags);
    16 void clr_flags(int fd,int flags);
    17 int main(int argc,char*argv[])
    18 {
    19     char buf[1024]={0};
    20     int ret;
    21 /*    flags=fcntl(0,F_GETFL,0);//先获取标准输入的标志
    22     if(flags==-1)
    23         ERR_EXIT("fcntl get flags error");
    24     ret=fcntl(0,F_SETFL,flags|O_NONBLOCK);//将标准输入设置为非阻塞,默认对读是阻塞的。不更改其他状态
    25     if(ret==-1)
    26         ERR_EXIT("fcntl set flags error");
    27 */    set_flags(0,O_NONBLOCK);//设置非阻塞,直接返回   (EAGIAN)read error: Resource temporarily unavailable(资源暂且不可用),如果是socket,会返回EWOUDBOCK
    28     //clr_flags(0,O_NONBLOCK);//清除
    29     ret=read(0,buf,1024);//标准输入读,read标准输入0默认阻塞(文件状态标志)
    30     if(ret==-1)
    31         ERR_EXIT("read error");
    32     printf("buf=%s
    ",buf);
    33     return 0;
    34 }
    35 void set_flags(int fd,int flags)
    36 {
    37     int val;
    38     val=fcntl(fd,F_GETFL,0);//先获取标准输入的标志
    39     if(val==-1)
    40         ERR_EXIT("fcntl get flags error");
    41     val |=flags;
    42     if(fcntl(fd,F_SETFL,val)<0)
    43         ERR_EXIT("fcntl set flags error");
    44 }
    45 void clr_flags(int fd,int flags)//清除状态
    46 {
    47     int val;
    48     val=fcntl(fd,F_GETFL,0);//先获取标准输入的标志
    49     if(val==-1)
    50         ERR_EXIT("fcntl get flags error");
    51     val&=(~flags);//原状态中与上 flags 的反
    52     if(fcntl(fd,F_SETFL,val)<0)
    53         ERR_EXIT("fcntl set flags error");
    54 }

    下面的例子讲解fcntl更改设置文件描述标志:

     1 //hello.c
     2 #include<unistd.h>
     3 #include<stdio.h>
     4 //hello程序打印程序环境变量
     5 extern char** environ;//指针的指针,指向一个指针数组 environ-->[...]数组中每一项指向一个环境信息。例如"TERM=VI00","SHELL=/bin/bash"
     6 int main(void)
     7 {
     8     printf("hello pid=%d
    ",getpid());
     9     //打印环境变量
    10     int i;
    11     for(i=0;environ[i]!=NULL;i++)
    12     {
    13         printf("%s
    ",environ[i]);
    14     }
    15     return 0;
    16 }
    17 
    18 //ececlp.标准输出在execlp中已经关闭,无法使用
    19 #include<unistd.h>
    20 #include<sys/types.h>
    21 #include<stdlib.h>
    22 #include<stdio.h>
    23 #include<errno.h>
    24 #include<fcntl.h>
    25 #define ERR_EXIT(m)
    26     do
    27     {
    28         perror(m);
    29         exit(EXIT_FAILURE);
    30     }while(0)  //宏要求一条语句
    31 int main()
    32 {
    33     printf("Entering main...
    ");
    34     int flag=fcntl(1,F_GETFD);
    35     int ret=fcntl(1,F_SETFD,flag|FD_CLOEXEC);//标准输出EXEC位置1
    36     if(ret==-1)
    37         perror("fcntl");
    38     //使用exec执行的程序里,此描述符被关闭,不能再使用它
    39     execlp("./hello","hello",NULL);//ececlp替换是成功的,但是标准输出EXEC位已经被置位,所以hello无法输出。
    40 /*输出结果
    41 Entering main...
    42 */
    43     printf("Exiting main...
    ");//不输出了
    44     return 0;
    45 }
  • 相关阅读:
    vlc-ts
    es 模板
    zookeeper 启动脚本
    received shard failed for shard id
    gitlab runner 配置
    kafka 配置文件注释
    logstash 统计告警
    BigBao 的python开发到DevOps 之路
    logstash 自动重新加载配置
    rsyslog 传输日志
  • 原文地址:https://www.cnblogs.com/wsw-seu/p/8289741.html
Copyright © 2011-2022 走看看