linux文件操作

来源:互联网 发布:手机虚拟网络能否上网 编辑:程序博客网 时间:2024/05/21 17:45

一、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 其他用户具可执行权限

my_chmod.c

#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

errno定义的那些内容可以通过程序输出(这里感谢殷大佬的提示)

#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.失败为-1

struct 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这个目录,就会报错。

原创粉丝点击