Linux文件操作

来源:互联网 发布:集搜客网络爬虫 下载 编辑:程序博客网 时间:2024/06/14 02:17

系统调用和设备驱动程序(系统调用是调用设备驱动程序的)
为了向用户提供一个一致的接口,设备驱动程序封装了所有与硬件相关的特性。
open:打开文件或设备
read:从打开的问价或设备里读数据
wirte:向文件或设备写数据
close:关闭文件或设备
ioctl:把控制信息传递给设备驱动程序

库函数
针对输入输出操作直接使用底层系统调用的一个问题是它们效率非常低
1)使用系统调用会影响系统的性能。与函数调用相比,系统调用的开销要大些,因为在执行系统调用时候,linux必须从运行用户代码切换到内核代码。然后再返回用户代码。减少这种开销的一个号方法是在程序中尽量减少系统调用的次数,并且让每次系统调用完成尽可能多的工作,例如:每次读写大量的数据而不是每次读写一个字符
2)硬件会限制底层系统调用一次所能读写的数据块大小
库函数则在数据满足数据块长度要求长度时候才安排执行底层系统调用,这就极大的降低了系统调用的开销。

底层文件访问:
每个运行中的程序被称为进程(process),它有一些与之关联的文件描述符。这是一些小值整数。可以通过它们访问打开的文件或设备。有多少文件描述符可用取决于系统的配置情况。
每当一个程序开始运行时:它一般会有3个已经打开的文件描述符
0:标准输入
1:标准输出
2:标准错误

open系统调用:
调用成功返回一个可以被read和write和其他系统调用使用的文件描述符(唯一的)。如果两个程序同时打开同一个文件,他们会分别得到两个不同的文件描述符。如果他们都对文件进行写操作。那么用他们会各写各的。调用失败返回一-1,并设置全局变量errno来指明失败原因

#include<fcntl.h>#include<sys/types.h>#include<sys/stat.h>int open(const char *path,int oflags);int open(const char *path,int oflags,mode_t mode);

path:文件的路径+文件名。若文件路径省略则是在当前目录下
oflags:用于指定打开文件所采取的动作
O_RDONLY以只读方式打开
O_WRONLY以只写方式打开
O_RDWR以读写方式打开 这三个必选一个且只能选一个
O_APPEND:把数据追加在文件的末尾
O_TRUNC:爸文件长度设置为0,丢弃已有的内容
O_CREAT:如果有此选项则采用第二个函数,启用mode参数
O_EXCL:与O_CREAT一起使用,确保调用者创建出文件。使用这个可 选模式可以防止两个程序同时创建同一个文件,如果文件已经存在则 open调用失败。
访问权限的初始值(mode)
S_IRUSR:读权限。文件属主
S_IWUSR:写权限。文件属主
S_IXUSR:执行权限 文件属主
S_IRGRP:读权限 文件属组
S_IWGRP:执行权限 文件属组
S_IXGRP:执行权限 文件属组
S_IROTH:读权限 其他用户
S_IWOTH:执行权限 其他用户
S_IXOTH:执行权限 其他用户

out=open("/root/test/aaa.out",O_WRONLY|O_CREAT|O_EXCL,S_IRUSR|S_IWUSR);[root@localhost mytest]# ls /root/test/aaa.out -l-rw------- 1 root root 0 Apr 13 22:38 /root/test/aaa.out

umask:系统变量,是由三位八进制整数组成的一个三位八进制数
三位从高到底以此是 用户,组,其他用户。
0表示允许相应任何权限
4禁止相应的读权限
2禁止相应的写权限
1禁止相应的执行权限
如果umask某一位被置为,则open中的参数将失效。

umask 600out=open("/root/test/aaa.out",O_WRONLY|O_CREAT|O_EXCL,S_IRUSR|S_IWUSR);[root@localhost mytest]# ls /root/test/aaa.out  -l---------- 1 root root 0 Apr 13 22:57 /root/test/aaa.out

可以看到创建的文件并没有属主可读和属主可写权限
write系统调用

#include<unistd,h>size_t write(int filds,const void *buf ,sizeof bnytes)

系统调用write的作用是把缓冲区buf的前nbytes个字节写入与文件描述符fildes关联的文件中。它返回实际的字节数。返回0表示没有写入任何数据,返回-1表示调用wrrite出现了错误,错误代码保存在全局变量errno里
read系统调用

#include<unistd.h>size_t  read(int fildes,void *buf,size_t bnytes);

从文件描述符fildes相关的文件里读入nbytes个字节的数据并存入数据区buf中,返回实际读入的字节数,返回0表示没有读入任何数据,已达到文件尾部,返回-1表示调用read出现了错误,
close系统调用
终止文件描述符fildes与其对应文件的关联,文件描述符被释放并能够从新使用,成功返回0,出错时返回-1

#include<unistd.h>int close(int fildes);

一个文件复制测试

#include<fcntl.h>#include<sys/types.h>#include<sys/stat.h>#include<unistd.h>int main(){        char c;        int in,out;        in=open("file.in",O_RDONLY);        if(in!=-1) write(1,"file.in is opened success!\n",28);          out=open("/root/test/mytest/file.out",O_RDWR|O_CREAT,S_IRUSR|S_IWUSR)        if(out!=-1) write(1,"file.out is created success!\n",29);        while(read(in,&c,1)==1) write(out,&c,1);        return 0;}
[root@localhost mytest]# cat file.in file.out total 40-rwxrwxrwx 1 root root 5370 Apr 13 23:54 a.out-rw-r--r-- 1 root root  308 Apr 13 07:24 copy_system.c-rw-r--r-- 1 root root    0 Apr 13 23:54 file.in-rw------- 1 root root  210 Apr 13 23:54 file.out-rw-r--r-- 1 root root  388 Apr 13 23:54 write.ctotal 40-rwxrwxrwx 1 root root 5370 Apr 13 23:54 a.out-rw-r--r-- 1 root root  308 Apr 13 07:24 copy_system.c-rw-r--r-- 1 root root    0 Apr 13 23:54 file.in-rw------- 1 root root  210 Apr 13 23:54 file.out-rw-r--r-- 1 root root  388 Apr 13 23:54 write.c

lseek系统调用
lseek系统调用对文件描述符fildes的读写指针进行设置,也就是说可以用它来设这里写代码片
置文件的下一个读写位置。

#include<unistd.h>#include<sys/types.h>off_t lseek(int fildes, off_t ,int whence)

fildes:文件描述符
offset:指定位置
whence:取值如下
SEEK_SET:表明offset是一个绝对位置
SEEK_CUR:表明offset是相对于当前位置的一个相对位置
SEEK_END:表明offset是相对于文件尾的一个相对位置

标准I/O库
与底层文件描述符对应的是流(stream),它被实现为指向结构FILE的指针
在启动程序时有三个文件流是自动打开的,stdin,stdout,stderr.分别代表标准输入,标准输出,标准错误输出。他们均在stdio.h头文件中定义 。
fopen函数
主要用于文件和终端的输入输出,如果需要对设备进行明确的控制,最好使用底层系统调用。
在成功调用时返回一个非空的FILE*指针,失败返回NULL
fread函数:

#include<stdio.h>siez_t fread(void *ptr ,size_t size,size_t nitems,FILE *stream)

数据从文件流strean读到ptr指向的数据 缓冲区里,fread和fwrite都是对数据记录进行操作,size参数指定每个数据记录的长度,计数器nitems给出要传输的记录个数,返回值是成功读到数据缓冲区里的记录个数而不是字节数。
fwrite函数

#include<stdio.h>size_t fwrite(const void *ptr,size_t size,size_t nitems,FILE *stream)

从指定的数据缓冲区读出数据记录,并写到输出流中,返回值是成功写入的记录个数
fclose

#include<stdio.h>int fclose(FILE *stream);

关闭指定的文件流stream

fseek函数

#include<stdio.h>int fseek(FILE *stream,long int offset,int whence);

参数用法与前面说的lseek是一样的,fseek返回一个整数:0成功 -1 失败 并设置errno指出错误

#include<stdio.h>int fgetc(FILE *stream);//遇到文件尾 返回EOF指针int getc(FILE *stream);int getchar();//从标准输入读取一个字符int fputc(int c,FILE *stream)int putc(int c,FILE *stream)int putchar(int c)

注意putchar和getchar都是把字符当做int类型而不是char类型来使用的,这就允许文件尾(EOF)表示取-1.
char *fgets(char *s ,int n,FILE *stream);
char *gets(chr *s);
fgets遇到换行符,已经传输了n-1个字符(最后一个为空字符以结束字符串),到达文件尾部,都会使函数调用终止。如果出现错误返回空指针并设置errno以指示出现错的类型
gets 从标准输入读取 ,并丢弃遇到的换行符,他在接受到的字符串的尾部加上一个null字节。

文件错误流:
为了表明错误许多stdio.h库函数会返回一个超出范围的值,比如空指针或EOF常数。此时错误由外部变量errno之处

#include<errno.h>extern  inr errno;

文件和目录的维护:
chmod

#include<sys/stat.h>int chmod(comst char *path,mode_t mode);mode和open中的mode取值一样S_IRUSR:读权限。文件属主S_IWUSR:写权限。文件属主S_IXUSR:执行权限 文件属主S_IRGRP:读权限  文件属组S_IWGRP:执行权限  文件属组S_IXGRP:执行权限  文件属组S_IROTH:读权限 其他用户    S_IWOTH:执行权限  其他用户    S_IXOTH:执行权限 其他用户#include<sys/types.h>#include<sys/stat.h>int mkdir(const char *path,mode_t mode); mode和open函数中的mode参数取值相同,并且受umask影响#include<unistd.h>int mkdir (const char *path);删除的是空目录#include<unistd.h>int chdir(const char *path)和cd一样char  *getcwd(char *buf,size_t size);将当前目录写到buf里,如果超过size,则返回NULL,若成功则返回指针buf

扫描目录
opendir函数;
打开一个目录并建立一个目录流,如果成功则返回一个指向DIR结构的指针,该指针用于读取目录数据项。失败则返回空指针。

#include<sys/types.h>#include<dirent.h>DIR *opendir(const char *name);

readir函数
函数返回一个指针,指针指向的结构里保存着目录流dirp中下一个目录项的有关资料,如果发生错误或者到达目录尾,将返回null.

#include<sys/types.h>#include<dirent.h>struct dirent *readdir(DIR *dirp);

telldir函数
返回值记录一个目录流里当前的位置,你可以在随后的seekdir调用中利用这个值来重置目录扫描到当前位置

#include<sys/types.h>#include<dirent.h>long int telldir(DIR *dirp);

seekdir函数
seekdir函数的作用是设置目录流dirp的目录项指针,loc的值用来设置指针位置,他应该通过前一个telldir调用获得
void seekdir(DIR *dirp,long int loc);
close函数
关闭一个目录流并释放与之关联的资源,执行成功时返回0,错误时返回-1

下面是一个扫描目录的程序

#include<sys/types.h>#include<dirent.h>int closedir(DIR *dirp);#include<unistd.h>#include<stdio.h>#include<dirent.h>#include<string.h>#include<sys/stat.h>#include<stdlib.h>void printdir(char *dir,int depth){    DIR *dp;    struct dirent *entry;    struct stat statbuf;    if((dp=opendir(dir))==NULL)//打开dir指向的目录并建立一个目录流给dp    {        printf("cannot open directory:%s\n",dir);               return ;    }    chdir(dir);//进入这个目录下    while((entry=readdir(dp))!=NULL){//如果当前目录中的下一个目录项不为孔        lstat(entry->d_name,&statbuf);//latat返回该链接指向文件的信息        if(S_ISDIR(statbuf.st_mode)){//如果是目录的话            if(strcmp(".",entry->d_name)==0||                strcmp("..",entry->d_name)==0)                continue;//如果是当前目录项和上一目录项则不打印            printf("%*s%s/\n",depth,"",entry->d_name);//打印目录,先打印depth个空格            printdir(entry->d_name,depth+4);//进入这个目录里        }        else    printf("%*s%s\n",depth,"",entry->d_name);//打印文件名    }    chdir("..");//回到上一层目录    closedir(dp);//关闭dir指向的目录建立的目录流}int main(){    printdir("/root/test",0);    return 0;}

运行结果如下

[root@localhost mytest]# ./a.out a2/    a2_2    a2_1printdir.cwrite.ca3/copy_system.cfile.out.write.c.swpfile.ina1/    a1_2    a1_1a.out
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 丰田雷凌保养手册丢了怎么办 海尔电视两年主板坏了怎么办 海信电视保修期内主板坏了怎么办 乐视电视的主板坏了怎么办 车电瓶没电了打不着火怎么办 面包车没电了打不着火怎么办 汽车电瓶没电了打不着火怎么办 自动挡的车没有电打不起来火怎么办 自动挡汽车没电了打不着火怎么办 自动挡小车没电了打不着火怎么办 被4s店销售骗了怎么办 宇通客车尿素泵不工作怎么办 汽车打蜡不小心打在车帮怎么办 海信电视怎么安装第三方软件怎么办 网上买票的时候不想用学生票怎么办 南方公园完整破碎讲话嘴不动怎么办 同一个安全员被锁在两个项目怎么办 家长拖欠家教老师的课时费怎么办 合同没到期房东不退押金怎么办 租房合同没到期房东要违约怎么办 档案存放费交了一年的延期怎么办 天津房子卖了户口没地方迁怎么办 中国到美国读计算机硕士签证怎么办 在江苏大学去德国读研怎么办? 宿舍上下铺的床一动就响怎么办 自助取款机存款忘打印了凭条怎么办 高一新生跨省转学籍怎么办 网上买票不小心买成了学生票怎么办 做横幅标语字打出来老是歪的怎么办 创业板股票暂停上市后钱怎么办 新股东入股公司之前的亏损怎么办 目前公司账面亏损有人要入股怎么办 土地确权后没有土地的人怎么办 老板不发工资跑路了怎么办 别人登录了我的美团账号怎么办 月嫂家政公司快坚持不下去了怎么办 华硕飞马4a手机发热怎么办 超级必发指数手机页面没曲线怎么办 唐小僧理财暴雷了投资者该怎么办 教师资格证面试准考证号忘了怎么办 初中学校说处分不给毕业证怎么办?