lseek,fcntl,ioctl函数

函数说明:
每一个已打开的文件都有一个读写位置, 当打开文件时通常其读写位置是指向文件开头, 若是以附加的方式打开文件(如O_APPEND), 则读写位置会指向文件尾. 当read()或write()时, 读写位置会随之增加,lseek()便是用来控制该文件的读写位置. 参数fildes 为已打开的文件描述词, 参数offset 为根据参数whence来移动读写位置的位移数.

注意其每个打开的文件都记录着当前读写位置,打开文件时读写位置是0,表示文件开头,通常读写多少个字节就会将读写位置往后移多少个字节。但是有一个例外,如果以O_APPEND方式打开,每次写操作都会在文件末尾追加数据,然后将读写位置移到新的文件末尾。lseek和标准I/O库的fseek函数类似,可以移动当前读写位置(或者叫偏移量)。

lseek扩展文件:

touch创建文件test,注意其大小为0:

#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
int main(void)
{
    int fd=open("test",O_RDWR);//假设已经存在test文件并且有读写权限
    if(fd<0)
    {
        perror("open test");
        exit(-1);
    }
    //扩展一个文件,一定要有写操作 0x1000为4096
    lseek(fd,0x1000,SEEK_SET);
    write(fd,"a",1);

    close(fd);
    return 0;
}

运行结果:

可以看到文件大小变成了4097,为4096加上我们写入的一个字符a。注意,如果程序中没有write函数进行写操作,test文件大小不会改变。

lseek获取文件大小: 

#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
int main(void)
{
    int fd=open("hello",O_RDWR);
    if(fd<0)
    {
        perror("open hello");
        exit(-1);
    }
    long long int len;
    //第二个参数到SEEK_END的长度,off_t在64为系统中,通常为long long int,32的为long
   len= lseek(fd,0,SEEK_END);
    printf("%lld\n",len);

    close(fd);
    return 0;
}

创建hello文件,写入hello文本,一共6个字符,包含最后一个\n.

输出:

通过od指令也可以看出大小为6.

 

fcntl
先前我们以read终端设备为例介绍了非阻塞I/O,为什么我们不直接对STDIN_FILENO做
非阻塞read,而要重新open一遍/dev/tty呢?因为STDIN_FILENO在程序启动时已经被自动
打开了,而我们需要在调用open时指定O_NONBLOCK标志。这里介绍另外一种办法,可以用
fcntl函数改变一个已打开的文件的属性,可以重新设置读、写、追加、非阻塞等标志(这
些标志称为File Status Flag),而不必重新open文件。

 

#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.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;
}

在图形界面的终端里多次改变终端窗口的大小并运行该程序,观察结果。

 没有人是所有内核驱动或者应用函数都记得的,所以很多时候,我们需要借助谷歌必应百度搜索,一点一点积累。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这些函数都是Linux系统调用,用于在用户空间程序和内核空间之间进行数据传输、设备控制等操作。 1. open(): 打开一个文件或设备,返回该文件或设备的文件描述符,该描述符用于后续的读、写、控制和关闭操作。语法如下: ``` #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *pathname, int flags); ``` 2. close(): 关闭一个文件或设备,释放该文件或设备占用的系统资源。语法如下: ``` #include <unistd.h> int close(int fd); ``` 3. read(): 从一个文件或设备中读取数据到指定的缓冲区中,返回实际读取的字节数。语法如下: ``` #include <unistd.h> ssize_t read(int fd, void *buf, size_t count); ``` 4. write(): 将数据从指定的缓冲区中写入到一个文件或设备中,返回实际写入的字节数。语法如下: ``` #include <unistd.h> ssize_t write(int fd, const void *buf, size_t count); ``` 5. lseek(): 在一个文件或设备中定位到指定的位置,返回新的位置偏移量。语法如下: ``` #include <unistd.h> off_t lseek(int fd, off_t offset, int whence); ``` 6. ioctl(): 对一个设备进行控制和定位操作,需要使用特定的命令码,并可携带相应的参数。语法如下: ``` #include <sys/ioctl.h> int ioctl(int fd, unsigned long request, ...); ``` 这些函数在Linux系统编程中非常常用,尤其是在设备驱动开发中。熟练掌握这些函数的使用方式和原理,对于开发高质量的Linux应用程序和驱动非常有帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值