6.1 fcntl 函数

6.1.1 函数介绍

 #include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock * lock);
  • 函数说明:fcntl()用来操作文件描述词的一些特性。
  • 函数功能:可以改变已经打开文件的性质
  • 参数说明
    • @fd:代表欲设置的文件描述符
    • @cmd:代表欲操作的指令。有以下几种情况:
      • F_DUPFD:用来查找大于或等于参数 arg 的最小且仍未使用的文件描述符,并且复制参数 fd 的文件描述符。执行成功则返回新复制的文件描述符。请参考dup2()。复制文件描述符,新的文件描述符作为函数返回值返回
      • F_GETFD:获取文件描述符,通过第三个参数设置
      • F_SETFD:设置文件描述符,通过第三个参数设置
      • F_GETFL/F_SETFL:
        • 取得/设置文件状态标志,通过第三个参数设置
        • 可以更改的几个标志是:O_APPEND、O_NONBLOCK、SYNC、O_ASYNC(O_RDONLY、O_WRONLY和O_RDWR不适用)
      • F_GETLK 取得文件锁定的状态。
      • F_SETLK 设置文件锁定的状态。此时flcok 结构的l_type 值必须是F_RDLCK、F_WRLCK或F_UNLCK。如果无法建立锁定,则返回-1,错误代码为EACCES 或EAGAIN。
      • F_SETLKW F_SETLK 作用相同,但是无法建立锁定时,此调用会一直等到锁定动作成功为止。若在等待锁定的过程中被信号中断时,会立即返回-1,错误代码为EINTR。
    • @参数lock指针为flock 结构指针,定义在下面。
  • 返回值:
    • 成功则返回0,若有错误则返回-1,错误原因存于errno。
  • 常见的功能:
    • 复制一个现存的描述符,新文件描述符作为函数返回值(cmd = F_DUPFD)
    • 获得/设置文件描述符标志(cmd = F_GETFD 或 F_SETFD)
    • 获得/设置文件状态标志(cmd = F_GETFL 或 F_SETFL)
    • 获得/设置文件锁(cmd = F_SETLK、cmd= F_GETLK、F_SETLKW)
      • 第三个参数为 struct flock 结构体,定义如下  
 struct flcok
{
short int l_type; /* 锁定的状态*/
short int l_whence;/*决定l_start位置*/
off_t l_start; /*锁定区域的开头位置*/
off_t l_len; /*锁定区域的大小*/
pid_t l_pid; /*锁定动作的进程*/
};
  • l_type 有三种状态:

    • F_RDLCK 建立一个供读取用的锁定
    • F_WRLCK 建立一个供写入用的锁定
    • F_UNLCK 删除之前建立的锁定
  • l_whence 也有三种方式:
    • SEEK_SET 以文件开头为锁定的起始位置。
    • SEEK_CUR 以目前文件读写位置为锁定的起始位置
    • SEEK_END 以文件结尾为锁定的起始位置。    

6.1.2 例子 

  文件状态标志设置

  io.h

 #ifndef __IO_H__
#define __IO_H__ extern void copy(int fdin, int fdout); 6 extern void set_fl(int fd, int flag);
7 extern void clr_fl(int fd, int flag);
#endif

  io.c

 #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "io.h"
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h> #define BUFFER_LEN 1024 /* 文件的读写拷贝 */
void copy(int fdin, int fdout)
{
char buff[BUFFER_LEN];
ssize_t size; // printf("file length: %ld\n", lseek(fdin, 0L, SEEK_END));//将文件定位到文件尾部,偏移量为0L
// lseek(fdin, 0L, SEEK_SET);// 定位到文件开头 while((size = read(fdin, buff, BUFFER_LEN)) > ) { //从 fdin 中读取 BUFFER_LEN 个字节存放入 buff 中
// printf("current: %ld\n", lseek(fdin, 0L, SEEK_CUR)); if(write(fdout, buff, size) != size) {
fprintf(stderr, "write error: %s\n", strerror(errno));
exit();
}
}
if(size < ) {
fprintf(stderr, "read error:%s\n", strerror(errno));
exit(); // 相当于 return 1;
}
} 39 void set_fl(int fd, int flag)
40 {
41 int val;
42
43 //获得原来的文件状态标志
44 val = fcntl(fd, F_GETFL);
45 if(val < 0) {
46 perror("fcntl error");
47 }
48
49 //增加新的文件状态标志
50 val |= flag;
51
52 //重新设置文件状态标志(val 为新的文件状态标志)
53 if(fcntl(fd, F_SETFL, val) < 0) {
54 perror("fcntl error");
55 }
56 }

58 void clr_fl(int fd, int flag)
59 {
60 int val;
61
62 val = fcntl(fd, F_GETFL);
63 if(val < 0) {
64 perror("fcntl error");
65 }
66 //清除指定的文件状态标志(设置为0)
67 val &= ~flag;
68 if(fcntl(fd, F_SETFL, val) < 0) {
69 perror("fcntl error");
70 }
71 }

  file_append.c

 #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include "io.h" int main(int argc, char *argv[])
{
if(argc < ) {
fprintf(stderr, "usage: %s content destfile\n", argv[]);
exit();
} int fd;
int ret;
size_t size; fd = open(argv[], O_WRONLY); //设置追加的文件状态标志
26 set_fl(fd, O_APPEND); //清除追加文件状态标志
//clr_fl(fd, O_APPEND);
/*
fd = open(argv[2], O_WRONLY | O_APPEND);
if(fd < 0){
perror("open error");
exit(1);
} */
/*
//定位到文件尾部
ret = lseek(fd, 0L, SEEK_END);
if(ret == -1) {
perror("lseek error");
close(fd);
exit(1);
}
*/
sleep(); //睡眠 10s //往文件中追加内容
size = strlen(argv[]) * sizeof(char);
if(write(fd, argv[], size) != size) {
perror("write error");
close(fd);
exit();
} return ;
}

  编译调试与 file_append 例子中相同

6.2 ioctl函数---io设备控制函数

 #include <unistd.h>
#include <sys/ioctl.h>
int ioctl(int fd, int cmd, …)
  • 函数说明:

    • ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。
    • ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就能在用户程序中使用ioctl函数控制设备的I/O通道。
    • 此函数可以说是 I/O操作的杂物箱。不能用前面说的函数表示的 I/O 操作通常都能用 ioctl 表示。
    • 终端 I/O 是 ioctl 的最大使用方面,主要用于设备 I/O 控制
  • 函数功能:
    • 控制I/O设备 ,提供了一种获得设备信息和向设备发送控制参数的手段。
    • 用于向设备发控制和配置命令 ,有些命令需要控制参数,这些数据是不能用read / write 读写的,称为Out-of-band数据。
    • 也就是说,read / write 读写的数据是in-band数据,是I/O操作的主体,而ioctl 命令传送的是控制信息,其中的数据是辅助的数据。
  • 参数说明:
    • @fd :就是用户程序打开设备时使用open函数返回的文件标示符,
    • @cmd :就是用户程序对设备的控制命令,
    • @.... : 省略号,那是一些补充参数,即可变参数列表,一般最多一个,有或没有是和cmd的意义相关的。
  • 返回值:成功为0,出错为-1

6.2.2 例子

  从键盘 IO 设备中,读取键盘的数据

 #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/input.h> int main(int argc, const char *argv[])
{
int fd = -;
char name[] = "Unknown";
struct input_event event;//事件源
int ret = ; if((fd = open("/dev/input/event1", O_RDONLY)) < ) {
perror("open error");
exit();
} //EVIOCGNAME 宏的作用是获得 IO 设备的名称
if(ioctl(fd, EVIOCGNAME(sizeof(name)), name) < ) {
perror("evdev ioctl error\n");
exit();
} printf("The device says its name is %s\n", name); //读写打开的设备文件
while() {
ret = read(fd, &event, sizeof(event));
if(ret < ) {
perror("read event error\n");
} if(EV_KEY == event.type) {
//如果事件是一个按键码
printf("key code is %d\n", event.code); if(event.code == ) {
//按 q 退出此应用程序
break;
}
}
} close(fd); return ;
}

  

六、文件IO——fcntl 函数 和 ioctl 函数的更多相关文章

  1. ioctl函数用法小记

    By francis_hao    Aug 27,2017   UNPV1对ioctl有算是比较详细的介绍,但是,这些request和后面的数据类型是从哪里来的,以及参数具体该如何使用呢?本文尝试在不 ...

  2. 文件IO

    在unix世界中视一切为文件,无论最基本的文本文件还是网络设备或是u盘,在内核看来它们的本质都是一样的.大多数文件IO操作只需要用到5个函数:open . read . write . lseek 以 ...

  3. Unix环境编程之文件IO

    1.文件IO 2.文件与目录 3.进程 4.多线程编程 5.信号 6.进程间通信 学习linux编程,首先要学会使用shell,这里一些基础命令就不介绍了.这里唯一要提的一个shell命令就是man. ...

  4. 第3章 文件I/O(4)_dup、dup2、fcntl和ioctl函数

    5. 其它I/O系统调用 (1)dup和dup2函数 头文件 #include<unistd.h> 函数 int dup(int oldfd); int dup2(int oldfd, i ...

  5. Linux系统编程(4)——文件与IO之ioctl函数

    ioctl是设备驱动程序中对设备的I/O通道进行管理的函数.所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率.马达的转速等等.它的参数个数如下:int ioctl(int ...

  6. 【Linux 应用编程】文件IO操作 - 常用函数

    Linux 系统中的各种输入输出,设计为"一切皆文件".各种各样的IO统一用文件形式访问. 文件类型及基本操作 Linux 系统的大部分系统资源都以文件形式提供给用户读写.这些文件 ...

  7. 文件IO函数和标准IO库的区别

    摘自 http://blog.chinaunix.net/uid-26565142-id-3051729.html 1,文件IO函数,在Unix中,有如下5个:open,read,write,lsee ...

  8. 文件I/O之ioctl函数

    ioctl函数是I/O操作的杂物箱.不能用其他函数表示的I/O操作通常都能用ioctl表示.终端I/O是ioctl的最大使用方面. ioctl函数通过对文件描述符发送特定的命令来控制文件描述符所代表的 ...

  9. Python文件操作函数os.open、io.open、内置函数open之间的关系

    Python提供了多种文件操作方式,这里简单介绍os.open.io.open.内置函数open之间的关系: 一.内置函数open和io.open实际上是同一个函数,后者是前者的别名: 二.os.op ...

随机推荐

  1. luogu3811 乘法逆元

    逆元定义:若a*x=1(mod p),(a,p互质),则x为a mod p意义下的逆元 做法见https://www.luogu.org/blog/zjp-shadow/cheng-fa-ni-yua ...

  2. 【git】git一些命令使用记录

    目前git版本控制很多公司都在用,我把平时的使用做些记录,防止忘记. 1. 有时候分支比较多,我们会基于master建立一个新分支开发,有时候也会基于别的分支建立,但时间长了可能会忘记当前分支是基于哪 ...

  3. Ubuntu18.04搜狗输入法最新版本2.2.0.0108经常乱码的解决方案

    图示 解决 旧版 可以安装旧版(我只在新版sogoupinyin_2.2.0.0108_amd64才遇到这个问题) 旧版安装指南:http://www.cnblogs.com/dunitian/p/6 ...

  4. poj1456 Supermarket

    书上用的方法是正着按照天数推,如果任务大于小根堆顶就替换,天数多于任务就加. 而我依稀记得以前洛谷上有一题也是这个,用时光倒流来求解,天数倒推,加任务,取大根堆顶即可. 我的代码实现: #includ ...

  5. pandas 读取excel文件对数据简单清洗并用matplotlib 将数据展示

    首先我们看下数据 接下来数据分析操作 import numpy as np import pandas as pd from matplotlib import pyplot as plt if __ ...

  6. Flask Mysql数据库连接

    下载库: pip install flask-sqlalchemy 下载后进入终端使用python后import导入模块测试没有报错就说明成功了 py文件: # -*- encoding: utf-8 ...

  7. 删除文件夹下面的文件的shell命令

    首先看我的文件所在目录 我想删除位于desktop下面的helloBox中的react-hello-dimple中的package.json文件,我们注意一下时间是4月18号 shell命令如下 $ ...

  8. numpy学习之前的必要数学知识:线性代数

    行列式 主要内容 1.行列式的定义及性质 2.行列式的展开公式 一.行列式的定义 1.排列和逆序 排列:由n个数1,2,…,n组成的一个有序数组称为一个n级排列,n级排列共有n!个 逆序:在一个排列中 ...

  9. C++基础知识--DAY1

    1. C语言是面向过程的语言,C++是面向对象的语言,相对于C语言来说,C++语法规则更为严格,其存在类型增强的问题. 类型增强,顾名思义就是C++相对于C语言来说有更加严格的类型检查,很多C语言的语 ...

  10. keepalived+LVS实现网站负载均衡和HA

    如上图所示,102和103是内网nginx服务器,100和101是边界LB,clinet是1,这个实验是为了实现在LB上虚拟出一个VIP,client通过访问该VIP,来动态负载到两台内网nginx服 ...