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. BZOJ3133[Baltic2013]ballmachine

    题目描述 https://www.lydsy.com/JudgeOnline/problem.php?id=3133 题解 还是分两个操作来说吧. 先看第一个操作,放球,可以发现,对于祖先节点和后代节 ...

  2. 使用BlockQueue实现生产者和消费者模式

    数据 package cn.lonecloud.procum; /** * @author lonecloud * @version v1.0 * @date 上午11:00 2018/5/7 */ ...

  3. UVALive - 4222

    题目链接:https://vjudge.net/contest/244167#problem/D 题目: For a dance to be proper in the Altered Culture ...

  4. 【洛谷P2860】冗余路径

    题目大意:给定一个 N 个点,M 条边组成的无向图,求至少在图中加入几条边才能使得整个图没有割边. 题解:求出该无向图的所有边双联通分量,每个边双联通分量可以理解成无向图的一个极大环,对该无向图进行缩 ...

  5. 【洛谷P2704】炮兵阵地

    题目大意:定义一个炮兵会影响该点所在坐标上下左右两个格子的范围,求一个 N*M 的网格里最多可以放多少个炮兵. 题解:发现这个问题有需要记录两个状态,即:上一层的状态和上两层的状态,若直接进行记录,空 ...

  6. MVC WebAPI框架里设置异常返回格式统一

    webApi里设置全局异常返回格式今天为了设置api返回格式统一,在网上找了一推资料,各种资料参差不齐的,最后自己捣鼓,终于弄出来了,直接上代码 /// <summary> /// 消息代 ...

  7. (贪心 模拟?) codeVs1098 均分纸牌

    题目描述 Description 有 N 堆纸牌,编号分别为 1,2,…, N.每堆上有若干张,但纸牌总数必为 N 的倍数.可以在任一堆上取若于张纸牌,然后移动. 移牌规则为:在编号为 1 堆上取的纸 ...

  8. ArrayList 实现随机点名

    package lijun.cn.demo1; import java.util.ArrayList; import java.util.Random; public class CallName { ...

  9. BZOJ4653 尺取法 + 线段树

    https://www.lydsy.com/JudgeOnline/problem.php?id=4653 首先很容易想到离散之后排序,用线段树或者树状数组去维护. 问题在于按照什么排序,如果按照左端 ...

  10. 数据挖掘的标准流程-CRISP-DM

    1.起源 CRISP-DM (cross-industry standard process for data mining), 即为"跨行业数据挖掘过程标准".此KDD(know ...