六、文件IO——fcntl 函数 和 ioctl 函数
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 函数的更多相关文章
- ioctl函数用法小记
By francis_hao Aug 27,2017 UNPV1对ioctl有算是比较详细的介绍,但是,这些request和后面的数据类型是从哪里来的,以及参数具体该如何使用呢?本文尝试在不 ...
- 文件IO
在unix世界中视一切为文件,无论最基本的文本文件还是网络设备或是u盘,在内核看来它们的本质都是一样的.大多数文件IO操作只需要用到5个函数:open . read . write . lseek 以 ...
- Unix环境编程之文件IO
1.文件IO 2.文件与目录 3.进程 4.多线程编程 5.信号 6.进程间通信 学习linux编程,首先要学会使用shell,这里一些基础命令就不介绍了.这里唯一要提的一个shell命令就是man. ...
- 第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 ...
- Linux系统编程(4)——文件与IO之ioctl函数
ioctl是设备驱动程序中对设备的I/O通道进行管理的函数.所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率.马达的转速等等.它的参数个数如下:int ioctl(int ...
- 【Linux 应用编程】文件IO操作 - 常用函数
Linux 系统中的各种输入输出,设计为"一切皆文件".各种各样的IO统一用文件形式访问. 文件类型及基本操作 Linux 系统的大部分系统资源都以文件形式提供给用户读写.这些文件 ...
- 文件IO函数和标准IO库的区别
摘自 http://blog.chinaunix.net/uid-26565142-id-3051729.html 1,文件IO函数,在Unix中,有如下5个:open,read,write,lsee ...
- 文件I/O之ioctl函数
ioctl函数是I/O操作的杂物箱.不能用其他函数表示的I/O操作通常都能用ioctl表示.终端I/O是ioctl的最大使用方面. ioctl函数通过对文件描述符发送特定的命令来控制文件描述符所代表的 ...
- Python文件操作函数os.open、io.open、内置函数open之间的关系
Python提供了多种文件操作方式,这里简单介绍os.open.io.open.内置函数open之间的关系: 一.内置函数open和io.open实际上是同一个函数,后者是前者的别名: 二.os.op ...
随机推荐
- 「SCOI2016」美味 解题报告
「SCOI2016」美味 状态极差无比,一个锤子题目而已 考虑每次对\(b\)和\(d\)求\(c=d \ xor \ (a+b)\)的最大值,因为异或每一位是独立的,所以我们可以尝试按位贪心. 如果 ...
- 「TJOI2015」旅游 解题报告
「TJOI2015」旅游 LCT沙比题 考虑我们其实是在维护一条链的\(\max\limits_{i<j} v_j-v_i\) 每次直接拿左右子树更新一下就可以了 写的时候把两个方向都维护一下, ...
- 单片机的外围功能电路 LET′S TRY“嵌入式编程”: 2 of 6
单片机的外围功能电路 LET′S TRY“嵌入式编程”: 2 of 6 本连载讲解作为嵌入式系统开发技术人员所必需具备的基础知识.这些基础知识是硬件和软件技术人员都应该掌握的共通技术知识. 上期在&l ...
- nodejs的某些api~(一)node的流1
根据心情整理一些node的api~ 今天第一篇,node的流:node的流比较重要,node的流存在于node的各个模块,包括输入输出流,stdin,stout.fs读取流,zlib流,crypto流 ...
- spring activemq 整合
创建maven项目 项目目录结构为 首先配置相关maven依赖 <!-- 版本管理 --> <properties> <springframework>4.1.8. ...
- NoSQL还是SQL?这一篇讲清楚
https://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=2653550127&idx=1&sn=93f79e007d757a ...
- vue2.0项目实战(5)vuex快速入门
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.Vuex 也集成到 Vue 的官方调试工具 ...
- linux系统调用之用户管理
getuid 获取用户标识号 setuid 设置用户标志号 getgid 获取组标识号 setgid 设置组标志号 getegid 获取有效组标识号 setegid 设置有效组标识号 geteuid ...
- Eclipse搭建SpringBoot之HelloWorld
你的eclipse需要先安装 Spring Tool Suite™ 第一种方法(不建议,之所以贴上是因为探索的过程) 首先新建Maven工程 勾选第一个按钮,第三个是选择working set ,你可 ...
- C和 C++的特点
C语言进化到C++ 的过程,是一个障眼法的发展过程.1. bool型变量:1个字节变量(和char一样大小),缺省赋值为true(1),false(0)2. 引用型变量:让新申请的变量挂在原有同类型的 ...