文件IO流中的三个函数,fcntl,ioctl,mmap函数

文件IO流中的三个函数,fcntl,ioctl,mmp函数


fcntl函数

之前写过一篇博客是关于linux系统IO方面的,这里是对其做的一些简单补充的一些函数信息。http://blog.csdn.net/qq_29924041/article/details/56497700
以前的相关函数,open,creat函数都是在打开或者创建文件的时候,去选择一些属性信心,如O_RDONLY,O_NONBLOCK等一些属性信息。但是如果在使用过程中的时候,需要改变其属性呢?这个时候再去重新打开一个,是极其不合理的吧,所以系统为我们提供了fcntl函数,这个函数就是用来在使用过程中来修改文件的相关属性的。
函数原型

#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);
参数:
    fd文件描述符。
    cmd:选择是获取还是修改。F_GETFL(获取)/F_SETFL(设置)
    arg:要设置的相关属性
属性类型参考上述链接部分的文章,可以为O_RDONLY,O_WRONLY,O_NONBLOCK等

代码实例:案例来自linuxC一站式编程

#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
    int val;
    if (argc != 2) {
    fputs("usage: a.out <descriptor#>\n", stderr);
        exit(1);
    }
    if ((val = fcntl(atoi(argv[1]), F_GETFL)) < 0) {
        printf("fcntl error for fd %d\n", atoi(argv[1]));
        exit(1);
    }
    switch(val & O_ACCMODE) {
        case O_RDONLY:
            printf("read only");
            break;
        case O_WRONLY:
            printf("write only");
            break;
        case O_RDWR:
            printf("read write");
        break;
            default:
        fputs("invalid access mode\n", stderr);
        exit(1);
    }
    if (val & O_APPEND)
            printf(", append");
    if (val & O_NONBLOCK)
            printf(", nonblocking");
        putchar('\n');
        return 0;
}

ioctl函数

与fcntl函数相似但是又完全不同的函数,ioctl函数。ioctl 用于向设备发控制和配置命令,有些命令也需要读写一些数据,但这些数据是不能用 read/write 读写的,称为 Out-of-band 数据,也就是说,read/write 读写的数据是 inband 数据,是 I/O 操作的主体,而 ioctl 命令传送的是控制信息,其中的数据是辅助的数据。
如;
例如,在串口线上收发数据通过 read/write 操作,而串口的波特率、校验位、停止位通过 ioctl 设置,A/D 转换的结果通过 read 读取,而 A/D 转换的精度和工作频率通过ioctl 设置
这些参数配置都是只能使用ioctl函数来进行配置的。

函数原型:

#include <sys/ioctl.h>
int ioctl(int d, int request, ...);
返回:若出错则返回-1,若成功则返回其他值,返回值也是取决于 request
参数:
    d 是某个设备的文件描述符
    request 是 ioctl 的命令,可变参数取决于 request,通常是一个指向变量或结构体的指针
    关于request的类型参考:
    https://baike.baidu.com/item/ioctl/6392403

实例代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
int main(void)
{
    struct winsize size;
    if (isatty(STDOUT_FILENO) == 0)
        exit(1);
    if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &size)<0) {
        perror("ioctl TIOCGWINSZ error");
    exit(1);
    }
    printf("%d rows, %d columns\n", size.ws_row, size.ws_col);
    return 0;
}

mmap函数

mmap 可以把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存地址,对文件的读写可以直接用指针来做而不需要 read/write 函数
如下图所示:
这里写图片描述
函数类型

#include <sys/mman.h>
void *mmap(void *addr, size_t len, int prot, int flag, int filedes, off_t off);
int munmap(void *addr, size_t len);
解析:
1:如果 addr 参数为 NULL,内核会自己在进程地址空间中选择合适的地址建立映射。      
2:如果addr 不是 NULL,则给内核一个提示,应该从什么地址开始映射,内核会选择 addr 之上的某个合适的地址开始映射
返回值:
    返回的是映射的地址
参数:
    len 参数是需要映射的那一部分文件的长度
    off 参数是从文件的什么位置开始映射,必须是页大小的整数倍(在 32 位体系统结构上通常是 4K)
    filedes 是代表该文件的描述符
    prot 参数:
        PROT_EXEC 表示映射的这一段可执行,例如映射共享库
        PROT_READ 表示映射的这一段可读
        PROT_WRITE 表示映射的这一段可写
        PROT_NONE 表示映射的这一段不可访问
    flag 参数有很多种取值
        MAP_SHARED 多个进程对同一个文件的映射是共享的,一个进程对映射的内存做了修改,另一个进程也会看到这种变化
        MAP_PRIVATE 多个进程对同一个文件的映射不是共享的,一个进程对映射的内存做了修改,另一个进程并不会看到这种变化,也不会真的写到文件中去
#include <stdlib.h>#include <sys/mman.h>
#include <fcntl.h>
int main(void)
{
    int *p;
    int fd = open("hello", O_RDWR);
    if (fd < 0) {
        perror("open hello");
    exit(1);
}
p = mmap(NULL, 6, PROT_WRITE, MAP_SHARED, fd, 0);
if (p == MAP_FAILED) {
    perror("mmap");
    exit(1);
}
    close(fd);
    p[0] = 0x30313233;
    munmap(p, 6);
    return 0;
}

以上案例来自linuxC一站式编程,其实有兴趣的可以自己去查阅相关书籍。

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值