linux文件操作
2017-07-23 14:11
169 查看
一、linux几个目录
1. /bin 用于储存普通用户可执行的命令,如ls,cp
2. /boot linux内核及启动系统是所需要的文件,保证启动文件安全
3. /dev 设备文件的储存目录,如硬盘,光驱(更体现一切皆文件)
4. /etc 用于存放系统的配置文件,比如账户密码
5. /home 普通用户主目录
6. /lib 用于存放各种库文件
7. /proc 该目录是一个虚拟文件系统,只有在系统运行时才存在。可以获取系统的状态信息并且修改某些系统的配置信息。cat/proc/memifo可以获取系统内存的使用状态
8. /sbin是用来存放用于管理系统的命令
9. /tmp 临时文件目录
10. /usr 用于存放系统应用程序及相关文件,如说明文档,帮助文档
11. /var用于存放系统中经常变化的文件,如日志文件,用户邮件
二、文件系统模型
物理磁盘的访问都是通过设备驱动程序进行的。对设备驱动的访问有两种途径:1、通过设备驱动本身提供的接口 2、通过虚拟文件系统提供给上层应用程序的接口(与proc相同,都是只存在与内存而不存在与磁盘之中)三、文件访问权限
1.r=4,w=2,x=1
2.int chmod(const char *path,mode_t mode)
和int fchmod(intflides,mode_t mode)
头文件是#include<sys/types.h>和
#include<sys/sta.h>
3.mode的参数
参数 | 八进制 | 含义 |
---|---|---|
S_IRUSR(S_IREAD) | 0400 | 文件所有者具可读 |
S_IWUSR(S_IWRITE) | 0200 | 文件所有者具可写入权限 |
S_IXUSR(S_IEXEC) | 00100 | 文件所有者具可执行权限 |
S_IRGRP | 00040 | 用户组具可读取权限 |
S_IWGRP | 00020 | 用户组具可写入权限 |
S_IXGRP | 00010 | 用户组具可执行权限 |
S_IROTH | 00004 | 其他用户具可读取权限 |
S_IWOTH | 00002 | 其他用户具可写入权限 |
S_IXOTH | 00001 | 其他用户具可执行权限 |
#include<stdio.h> #include<stdlib.h> #include<sys/types.h> #include<sys/stat.h> int main(int argc,char **argv) { int mode; int mode_u; int mode_g; int mode_o; char *path; if(argc<3)//保证和命令chmod的参数相同 { printf("%s <mode num> <target file>\n",argv[0]); exit(0); } mode=atoi(argv[1]);//这里默认你现在获得的参数就是8进制 if(mode>777||mode<0)//保证输入在范围之内 { printf("mode num error\n"); exit(0); } mode_u=mode/100;//求出各个位数 mode_g=(mode-(mode_u*100))/10; mode_o=mode-(mode_u*100)-(mode_g*10); mode=(mode_u*8*8)+mode_g*8+mode_o;//这里是8进制转换为十进制 path=argv[2];//实际就是将字符串首地址给了path if(chmod(path,mode)==-1)//chmod会认为你输入就是10进制,内部会处理,所以这个chmod程序只能说是一个简化 { perror("chmod errorr");//输出错误信息 //perror(s) 用来将上一个函数发生错误的原因输出到标准设备(stderr) exit(1); } return 0; }
四、文件打开和关闭
1、open函数
#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> int open(const char *pathname,int flags) int open(const char *pathname,int flags,mode_t mode); //具体用哪一个,是由参数flags决定
2.creat函数
int creat(const char *pathname,mode_t mode);creat只能以只写的方式打开创建的文件
3.close函数
int clode(int fd)- 成功调用返回一个文件描述符号,否则返回-1
my_creat.c
#include<stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #include<errno.h> #include<stdlib.h> #include<string.h> int main() { int fd; if((fd=open("example_62.c",O_CREAT|O_EXCL,S_IRUSR|S_IWUSR))==-1) // if((fd=creat("example_62.c",S_IRWXU))==-1) { perror("open"); // printf("open:%s with errno:%d\n",strerror(errno),errno);/;/strerror会把错误以字符串形式输出,errno是全局变量对应数字是错误 exit(1); } else { printf("create file success!\n"); } close(fd); return 0; }
mode参数 | 含义 |
---|---|
O_RDONLY | 只读打开 |
O_WRONLY | 只写打开 |
O_RDWR | 读写打开 |
O_SEARCH | (仅对目录有意义)只搜索打开 |
O_APPEND | 每次写文件时都追加到文件的尾部 |
O_CLOEXEC | 将FD_CLOEXEC设置为文件描述符标志 |
O_CREAT | 若该文件不存在则创建 |
O_EXCL | (指定了O_CREAT)若文件已存在则报错 |
O_NOFOLLOW | 若文件是一个符号链接则报错 |
O_SYNC | 对文件的修改将阻塞直到物理磁盘上同步为止 |
O_DIRECTORY | 若文件不是一个目录则失败 |
O_NONBLOCK | 以非阻塞的方式打开文件 |
O_NDELAY | 以非阻塞方式打开文件 |
O_TRUNC | 当文件存在并以可写方式打开则截断文件至0 |
#include<stdio.h> #include<sys/stat.h> #include<sys/types.h> #include<string.h> #include<errno.h> int main(void) { int i; for(i = 0;i < 140;i++) { errno = i; printf("%d error:%s\n",errno,strerror(errno)); } return 0; }
五、文件的读写
1、read函数
#include<unistd.h> ssize_t read(int fd,void *buf,size_t count); //从文件描述符fd所指向的文件中读取count个字节到buf中 //返回值表示世界读取字节数
2、write是从buf中读取count个字节到fd中
返回值相同3、lseek函数
#include<unistd.h> #include<sys/types.h> //和fseek类似
注意:
①fseek()不像lseek()会返回读写位置, 因此必须使用ftell()来取得目前读写的位置.
②lseek当调用成功时则返回目前的读写位置, 也就是距离文件开头多少个字节. 若有错误则返回-1, errno 会存放错误代码.
#include<stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<unistd.h> #include<errno.h> #include<string.h> #include<stdlib.h> void my_err(const char *err_string,int line)//错误处理 { fprintf(stderr,"line:%d ",line); perror(err_string); exit(1); } int my_read(int fd)//读数据 { int len; int ret; int i; char read_buf[64]; //SEEK_END表示结束 //SEEK_SET表示开头 //SEEK_CUR表示当前位置 if(lseek(fd,0,SEEK_END)==-1) my_err("lseek",__LINE__); if((len=lseek(fd,0,SEEK_CUR))==-1) my_err("lseek",__LINE__); if((lseek(fd,0,SEEK_SET))==-1) my_err("lseek",__LINE__); if((ret=read(fd,read_buf,len))<0) my_err("read",__LINE__); printf("len:%d\n",len); for(i=0;i<len;i++) { printf("%c",read_buf[i]); } putchar('\n'); return ret; } int main() { int fd; char write_buf[32]="hello,world!"; //if((fd=creat("example_63.c",S_IRWXU))==-1) if((fd=open("example_63.c",O_RDWR|O_CREAT|O_TRUNC,S_IRWXU))==-1) { my_err("open",__LINE__); } else printf("create file success\n"); //写数据 if(write(fd,write_buf,strlen(write_buf))!=strlen(write_buf)) my_err("write",__LINE__); my_read(fd); printf("/*-----------------*/\n"); if(lseek(fd,10,SEEK_END)==-1) my_err("lseek",__LINE__); if(write(fd,write_buf,strlen(write_buf))!=strlen(write_buf)) my_err("write",__LINE__); my_read(fd); close(fd); return 0; }
六、fcntl系统调用
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)
#include<stdio.h> #include<unistd.h> #include<fcntl.h> #include<sys/types.h> #include<sys/stat.h> #include<stdlib.h> void my_err(const char *err_string,int line)//错误处理函数 { fprintf(stderr,"line:%d ",line); perror(err_string); exit(1); } int main() { int ret; int access_mode; int fd; if((fd=open("example_64",O_CREAT|O_TRUNC|O_RDWR,S_IRWXU))==-1) my_err("open",__LINE__); if((ret=fcntl(fd,F_SETFL,O_APPEND))<0)//设置文件打开方式 my_err("fcntl",__LINE__); if((ret=fcntl(fd,F_GETFL,0))<0)//获取文件打开方式 my_err("fcntl",__LINE__); access_mode=ret & O_ACCMODE;//O_ACCMODE为3,&可以获得ret后两位 if(access_mode==O_RDONLY) printf("example_64 access_mode:read only"); else if(access_mode==O_WRONLY) printf("example_64 access_mode:write only"); else if(access_mode==O_RDWR) printf("example_64 access_mode:write+read"); if(ret&O_APPEND) printf(" ,append"); printf("\n%d\n",O_APPEND); printf("\n%d\n",O_NONBLOCK); printf("\n%d\n",O_SYNC); if(ret&O_NONBLOCK) printf(",nonblock"); if(ret&O_SYNC) printf(" ,sync"); putchar('\n'); return 0; }
2、锁
共享锁言简意赅就是说大家可以读这个文件
互斥锁就是只能一个人去写这个文件,防止不同人打开,最后文件混乱
int fcntl(int fd,int cmd,struct flock *lock)
struct flock { short l_type;/*锁的类型F_RDLCK, F_WRLCK, or F_UNLCK*/ off_t l_start;/*相对于l_whence的偏移值,字节为单位*/ short l_whence;/*从哪里开始:SEEK_SET, SEEK_CUR, or SEEK_END*/ off_t l_len;/*长度, 字节为单位; 0 意味着缩到文件结尾*/ pid_t l_pid;/*returned with F_GETLK*/ };
注意:
①cmd为中有一个F_GETTLK只是修改了结构体中锁的类型为F_UNLCK
②程序只是一个进程的时候可以设置写锁之后,设置读锁,但是多个进程的锁是不兼容的,所以下面的例子是单个进程
#include<stdio.h> #include<unistd.h> #include<fcntl.h> #include<sys/types.h> #include<sys/stat.h> #include<string.h> #include<stdlib.h> void my_err(const char *err_string,int line) { fprintf(stderr,"line:%d ",line); perror(err_string); exit(1); } //锁的设置或释放 int lock_set(int fd,struct flock *lock) { if(fcntl(fd,F_SETLK,lock)==0) { if(lock->l_type==F_RDLCK) printf("set read lock,pid:%d\n",getpid()); //getpid()取得进程识别码 else if(lock->l_type==F_WRLCK) printf("set write lock,pid:%d\n",getpid()); else if(lock->l_type==F_UNLCK) printf("release lock,pid:%d\n",getpid()); } else { perror("lock operation fail\n"); return -1; } } //测试锁 int lock_test(int fd,struct flock *lock) { if(fcntl(fd,F_GETLK,lock)==0) { if(lock->l_type==F_UNLCK) { printf("lock can be set in fd\n"); return 0; } else { if(lock->l_type==F_RDLCK) printf("can't set lock,read lock has been set by:%d\n",lock->l_pid); else if(lock->l_type==F_WRLCK) printf("can't set lock,write lock has been set by:%d\n",lock->l_pid); } return -2; } else { perror("get incompatible locks fail"); return -1; } } int main() { int fd; int ret; struct flock lock; char read_buf[32]; //打开文件 if((fd=open("example_65",O_CREAT|O_TRUNC|O_RDWR,S_IRWXU))==-1) my_err("open",__LINE__); if(write(fd,"test lock",10)!=10) my_err("write",__LINE__); //初始化 memset(&lock,0,sizeof(struct flock)); lock.l_start=SEEK_SET; lock.l_whence=0; lock.l_len=0; //设置读锁 lock.l_type=F_RDLCK;//就是检测可不可以设置读锁 if(lock_test(fd,&lock)==0) { lock.l_type=F_RDLCK; lock_set(fd,&lock); } //读数据 lseek(fd,0,SEEK_SET); if((ret=read(fd,read_buf,10))<0) my_err("read",__LINE__); read_buf[ret]='\0'; printf("%s\n",read_buf); //任意键 getchar(); //设置写锁 lock.l_type=F_WRLCK; if(lock_test(fd,&lock)==0) { lock.l_type=F_WRLCK; lock_set(fd,&lock); } //释放锁 lock.l_type=F_UNLCK; lock_set(fd,&lock); close(fd); return 0; }
七、文件属性操作
1、获取文件属性int lstat(int fileds,char *file_name,struct stat*buf)
执行成功为0.失败为-1struct stat { dev_t st_dev; /*文件所在设备的ID*/ ino_t st_ino; /* 节点号*/ mode_t st_mode; /* 文件的类型和存取的权限*/ nlink_t st_nlink; /* 链向此文件的连接数(硬连接)*/ uid_t st_uid; /* user's id*/ gid_t st_gid; /* group's id*/ dev_t st_rdev; /* 设备号,针对设备文件*/ off_t st_size; /* 文件大小,字节为单位*/ blksize_t st_blksize; /* 系统块的大小*/ blkcnt_t st_blocks; /* 文件所占块数*/ time_t st_atime; /* 最近存取时间*/ time_t st_mtime; /* 最近修改时间*/ time_t st_ctime; /*最后状态修改时间*/ };
宏定义好的几个函数
参数 | 含义 |
---|---|
S_ISLNK(st_mode) | 是否是一个连接 |
S_ISREG(st_mode) | 是否是一个常规文件 |
S_ISDIR(st_mode) | 是否是一个目录 |
S_ISCHR(st_mode) | 是否是一个字符设备 |
S_ISBLK(st_mode) | 是否是一个块设备 |
S_ISFIFO(st_mode) | 是否 是一个FIFO文件 |
S_ISSOCK(st_mode) | 是否是一个SOCKET文件 |
2、设置文件属性
mode_t unmask(mode_t mask)屏蔽属性#include<stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdlib.h> int main() { umask(0);//不屏蔽 if(creat("example_681.test",S_IRWXU|S_IRWXG|S_IRWXO)<0) { perror("creat"); exit(1); } umask(S_IRWXO);//其他用户没有可读可写可执行 if(creat("example_682.test",S_IRWXU|S_IRWXG|S_IRWXO)<0) { perror("creat"); exit(1); } return 0; }
八、目录的创建和删除、切换
1、目录的创建
#include<sys/stat.h> #include<sys/typed.h> int mkdir(const char *pathname,mode_t mode);
2、目录删除
#include<unistd.h> int mkdir(const char *pathanme)
注意:只能删除空目录
3、获取当前目录
#include<unistd.h> char *getcwd(char *buf,size_t size); char *get_current_dir_name(void) char *getwd(char *buf)
①get_current_dir_name获取当前工作目录
#define _GNU_SOURCE /*这是用来让用户配置编译环境的头文件。再看一下_GUN_SOURCE这个宏,这个宏可以让用户打开所有features.h文件的属性,而且其他头文件在获得这个宏定义之后才可以使用get——current_dir_name这个函数*/ #include<stdio.h> #include <stdio.h> #include <unistd.h> #include<stdlib.h> int main(int argc,char *argv[]) { char *path; path = get_current_dir_name(); printf("%s>\n",path); exit(0); } /*用gcc -E将预处理的代码导出来查看,如果宏定义的位置不正确。 导出的代码中不会包含get_current_dir_name()的函数原型,自然编译就认为它的返回值是默认的整数,从而导致一个警告。 把宏定义放在前面之后,gcc -E导出的代码中已经包含了正确的函数原型,警告就不会出现了。*/
②getcwd函数获取绝对路径
#include<stdio.h> #include<stdlib.h> #include<unistd.h> int main(void) { char *path = NULL; path = getcwd(NULL,0); /*或者使用方法getcwd(path,256),256是给path分配的空间,path就储存了空间*/ puts(path); free(path); return 0; } /*可以采取令 buf 为 NULL并使 size 为零,来使 getcwd 调用 malloc 动态给 buf 分配,但是这种情况要特别注意使用后释放缓冲以防止内存泄漏。*/
4、切换工作目录
#include<unistd.h> int chdir(const char *path);//path是目录参数 int fchdir(int fd);//fd是文件描述符号
例子是fchdir的使用
#include<stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main() { int fd; fd = open("../", O_RDONLY); fchdir(fd); printf("current working directory : %s \n", getcwd(NULL, 0)); close(fd); }
九、获取目录信息
1、opendir
#include<sys/types.h>
#include<dirent.h>
DIR *opendir(const char *name)
失败返回NULL
2.readdir
#include<sys/types.h>
#include<dirent.h>
原型DIR *readdir(DIR*dir)
struct dirent{ long d_ino;//索引节点号 off_t d_off;//在文件中偏移量 unsigned short d_reclen;//文件名长 char d_name[NAME_MAX+1]; }
3.closedir
#include<sys/types.h>
#include<dirent.h>
原型DIR *closedir(DIR*dir)
#include<stdio.h> #include<dirent.h> #include<unistd.h> #include<stdio.h> #include<stdlib.h> int my_readir(const char *path) { DIR *dir; struct dirent *ptr; if((dir=opendir(path))==NULL) { perror("opendir"); return -1; } while((ptr=readdir(dir))!=NULL)//直到NULL才会停止读取 printf("File name:%s\n",ptr->d_name); closedir(dir); return 0; } int main(int argc,char *argv[]) { if(argc<2)//判断参数 { printf("listfile <target path>\n"); exit(1); } if(my_readir(argv[1])<0) exit(1); return 0; }
注意:
这里所说的打开目录,只是获取了目录的信息,没有实际的进入你所打开的目录,你可以获取进入目录的名字,如果想切换目录,必须用chdir或fdir。用opendir打开,如果再想更深层次进入打开目录的目录是不可以的,opendir没有将你的目录切换。
比如你在linux目录下有一个ls目录,你打开了ls,发现ls目录下有个fun目录,你想进fun看看有什么,你会再次用opendir打开fun这个目录,但是实际上opendir会在linux目录下找fun,因为你的工作目录没有切换,当然linux下没有fun这个目录,就会报错。
相关文章推荐
- Linux文件基本操作管理
- linux-2 文件的一般操作
- linux用户组、/etc/group文件及账户相关操作命令
- linux 目录结构及文件基本操作
- Linux——文件操作
- 【Unix/Linux】【命令】【文件,目录操作工具】列出所有子目录与文件——ls (ll)命令
- Linux文件操作学习总结
- linux文件操作的一些函数
- Linux文件与目录操作函数
- Linux 文件操作中的阻塞和非阻塞操作
- linux文件操作二(文件定位和状态函数)
- linux 目录结构及文件基本操作
- Linux文件和目录的操作(五) rm rmdir
- Linux中shell文件操作大全
- Linux:目录&文件基本操作
- C拾遗(五)Linux文件操作
- linux下面文件字符操作总结函数集锦
- linux的文件io操作(转)
- linux下拷贝命令中的文件过滤操作记录
- Linux文件操作(二)