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;
}

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

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

posted @ 2017-06-26 17:18  Crystal_Guang  阅读(705)  评论(2编辑  收藏  举报