Linux文件操作

来源:互联网 发布:mac重装老失败 编辑:程序博客网 时间:2024/06/11 13:03

tags: Linux 文件


    • 文件概念
    • SNSI C标准文件IO操作
    • Linux文件结构
      • 简述
      • 文件分类
      • 文件访问权限
      • 文件操作
        • 文件打开
        • 文件创建
        • 文件关闭
        • 文件读
        • 文件写
        • 文件定位
        • dup dup2 fcntl ioctl系统调用
        • 文件属性操作
        • 文件的移动和删除
        • 目录创建
        • 目录删除
        • 目录其他操作
        • 目录打开
        • 目录关闭


1. 文件概念

  • 文本文件:每个字节存放一个ASCII码字符
  • 二进制文件:数据按其在内存中的存储形式原样存放
  • 缓冲区文件系统:系统自动为正在使用的问价开辟内存缓冲区。如:遵循SNSI标准的I/O函数
  • 非缓冲区文件系统:用户在程序中为每个文件设定缓冲区,每访问一次都需要执行一次系统调用。如:遵循POSIX标准的系统调用I/O函数
  • ANSI标准C函数使用全缓冲,行缓冲,无缓冲3中缓冲区处理方式
  • 系统启动时默认打开3个流:stdin, stdout, stderr.

2. SNSI C标准文件I/O操作

3. Linux文件结构

简述

  1. /bin:存放普通用户的可执行命令
  2. /boot:Linux内核及启动系统时所需要的文件
  3. /dev:设备文件
  4. /etc:存放系统的配置文件
  5. /home:普通用户的主目录
  6. /lib:存放库文件
  7. /proc:虚拟文件系统,只在系统运行时存在,可以获取系统的状态信息并且修改某些系统的配置信息
  8. /root:超级用户的家目录
  9. /sbin:存放用于管理系统的命令
  10. /tmp:临时文件目录
  11. /usr:用于存放系统应用改程序及相关文件
  12. /var:用于存放系统中经常变化的文件。

  • 对物理磁盘的访问都是通过设备驱动程序来进行的,有两种途径
    1. 通过设备驱动本身提供的接口(会给系统带来不确定性)
    2. 通过虚拟文件系统(vfs)提供的应用程序接口。

文件分类

  1. 普通文件:对普通文件的解释由应用程序完成
  2. 目录文件:只有内核可以写文件目录
  3. 字符特殊文件:表示系统中字符类型的设备,比如键盘,鼠标
  4. 块特殊文件:表示系统中块类型设备,如硬盘,光驱等
  5. FIFO:命名管道用于进程间通信
  6. 套接字:用于网络通信
  7. 符号连接:是另一个文件的引用

文件访问权限

  1. int chmod(const char* path, mode_t mode
    • 以文件名作为第一参数
  2. int fchmod(int fildes, mode_t mode)
    • 以文件描述符作为第一参数
    • 成功返回0,失败返回-1,错误代码存于系统预定义变量errno中
字符常量值 八进制值 含义 S_IRUSR(S_IREAD) 00400 文件所有者具有可读权限 S_IWUSR(S_IWRITE) 00200 文件所有者具有可写权限 S_IXUSR(S_IEXEC) 00100 文件所有者具有可执行权限 S_IRGRP 00040 用户组具有可读权限 S_IWGRP 00020 用户组具有可写权限 S_IXGRP 00010 用户组具有可执行权限 S_IROTH 00004 其他用户具有可读权限 S_IWOTH 00002 其他用户具有可写权限 S_IXOTH 00001 其他用户具有可执行权限 S_ISUID 04000 文件的set user-id on execution 位 S_ISGID 02000 文件的set group-id on execution 位 S_ISVTX 01000 文件的sticky位

文件操作

文件打开

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode)

  • pathname:要打开或创建的含路径的文件名
  • flags: 打开方式
    1. O_RDONLY :只读
    2. O_WRONLY :只写
    3. O_RDWR :读写
  • 可以与下列标志进行或运算
    1. O_CREAT :不存在自动创建,需要mode指明权限。新文件的权限是mode&~umask运算后的权限
    2. O_EXCL :如果O_CREAT被设置,不存在自动创建,存在打开错误
    3. O_TRUNC :若文件存在并且以可写方式打开,将文件长度清零,文件属性不变
    4. O_APPEND:追加
    5. O_SYNC:任何对文件的修改会阻塞,知道物理磁盘上的数据同步以后才返回
    6. O_NOFOLLOW:如果文件为符号连接,打开失败
    7. O_DIRECTORY:如果不是目录,打开失败
    8. O_NONBLOCK或O_NDELAY:以非阻塞方式打开,对于open和随后的操作都会立即返回。

文件创建

int create(const char *pathname, mode_t mode)

  • 如果文件已经存在则会被新文件覆盖,如果不存在创建
  • 相当于open(pathname, (O_CREAT|O_WRONLY|O_TRUCN)
  • 成功调用后返回一个文件描述符,错误会-1
  • 无法创建设备文件,设备文件要使用mknod函数

文件关闭

int close(int fd)

  • 成功返回0,错误返回-1
  • 成功时,并不代表数据全部写会硬盘
  • 进程结束时,内核会自动关闭所有的文件

文件读

ssize_t read(int fd, void *buf, size_t count)

  • 从fd指向的文件中读取count字节的数据到buf
  • 返回值代表实际读取的字节数
  • 返回0,表示到达文件尾,或者没有可读取的数据。错误返回-1

文件写

ssize_t write(int fd, const void *buf, size_t count)

  • 调用成功返回写入的字节数,错误返回-1

文件定位

off_t lseek(int fildes, off_t offset, int whence)

  • 用来公职读写位置
  • whence取值
    1. SEEK_SET 文件开始处计算偏移
    2. SEEK_CUR 当前位置计算偏移,offset允许负值
    3. SEEK_END 文件结束处计算偏移,offset允许负值
  • lseek允许文件指针设置到文件结束符EOF之后,如果这样,EOF处后写入的数据之间将会存在一个间隔,如果使用read读取这个间隔的数据会得到数据0
  • 当调用成功时返回当前的读写位置,也就是距离文件开始处多少个字节,错误返回-1

dup, dup2, fcntl, ioctl系统调用

int dup(int oldfd);
int dup2(int oldfd, int newfd)

  • dup用来复制参数oldfd所指的文件描述符,复制成功时返回最小尚未被使用的文件描述符,错误返回-1
  • 返回的新文件描述符合参数oldfd指向同一个文件,共享所有的锁定,读写指针和各项权限和标志位。两个描述符的操作是同步的
  • dup2可以指定新文件描述符的值,如果newfd被进程使用,系统会将其关闭。如果两个相等,不关闭,返回newfd,调用成功返回新的描述符,错误返回-1

fcntl(int fd, int cmd)
fcntl(int fd, int cmd, long arg)
fcntl(int fd, int cmd, struct flock *lock)

  • cmd

    1. F_DUPFD:功能与dup一样
    2. F_GETFD:用来获取close-on-exec标志,成功返回标志值,若标志值最后一位是0,则该标志没有被设置,意味着在执行exec相关函数后文件描述符仍保持打开,否则在执行exec后将关闭文件描述符。失败返回-1
    3. F_SETFD:设置文件描述符的close-on-exec标志位第三个参数arg的最后一位。成功返回0失败-1
    4. F_GETFL:获得文件的打开方式,成功返回标志值,失败-1
    5. F_SETFL:设置文件打开的方式为设置O_APPEND,O_NONBLOCK,O_SAYNC标志
    6. F_SETLK:用来设置或者释放锁,当l_type取F_UNLCK时释放锁,如果锁被其他进程占用,返回-1,设置errno为EACCES或EAGAIN。当设置一个读锁时,分段所指向的文件必须以可读方式打开,设置写锁时fd指向的文件必须以可写方式打开。当设置两种锁时,fd指向的文件必须以读写方式打开,fd被close时,锁会自动释放
    7. F_SETLKW:与cmd取F_SETLK时类似,不同的是当希望设置的锁因为存在其他锁而被阻止 设置时,该命令会一直等待冲突的锁被释放
    8. F_GETLK:lock指向一个希望设置的锁的属性的结构,如果锁能被设置,该命令并不真的设置锁,而是只修改lock的l_type域为F_UNLCK,然后返回。如果存在一个或多个锁与希望设置的锁冲突时会返回第一个锁的flock结构
    9. F_GETOWN 返回接受SIGIO或SIGURG信号的进程ID或进程组,进程组ID以负值返回
    10. F_SETOWN 设置进程或进程组接受SIGIO和SIGURG信号,进程组ID以负值指定,进程ID用正值指定
    11. F_GETSIG 可在输入输出是获得发送信号
    12. F_SETSIG 设置在输入输出时发送的信号
  • cmd取6,7,8时成功返回0,失败-1.

struct flock {    short_l_type;   //锁的类型    short_l_whence; //偏移起始位置    off_t_l_start;  //开始位置    off_t_l_len;    //锁定的字节数    pid_t_l_pid;   //所得属主进程id};
  • 对于有些应用程序,有事进程需要确保它正在单独写一个文件。Linux提供了记录锁机制
  • l_type用来指定的是共享锁(F_RDLCK,读锁)还是互斥锁(F_WDLCK,写锁)
  • 读锁可以多个进程同时使用,写锁只能一个进程单独使用
  • 一个进程只能设置某一文件区域上的一种锁。
  • 为了锁定整个文件,通常将l_start说明为0,l_whence说明为SEEK_SET,l_len说明为0

int ioctl(int fd, int request, …)

  • 用来控制特殊设备文件的属性,分段必须是一个已经打开的文件描述符,第三个参数一般为char *argp,随request不同而不同

文件属性操作

int stat(const char* filename, struct stat *buf)
int fstat(int filedes, struct stat *buf)
int lstat(const char *file_name, strutc stat *buf);

  • 执行成功时返回0,失败返回-1
  • stat:用于获取file_name指定的文件名的状态信息,保存在buf中
  • fstat是通过文件描述符来指定文件的,
  • 对于链接文件lstat返回的是符号链接文件本身的状态信息,stat返回的是符号链接指向的文件状态信息
struct stat {    dev_t   st_dev;   //文件设备编号    ino_t   st_ino;     //i节点编号    mode_t  st_mode;    //文件类型和存取权限    nlink_t st_nlink;  //连到该文件的硬链接数目,刚建立的文件值是1    uid_t   st_uid; //文件所有者的用户ID    gid_t   st_gid; //文件所有者的组id    dev_t   st_rdev; //若是设备文件,则为设备编号    off_t   st_size; //文件大小    blksize_t   st_blksize; //文件系统I/O缓冲区大小    blkcnt_t    st_blocks; //占用文件区块个数,每个512字节    time_t  st_atime; //最近一次被访问的时间    time_t  st_mtime; //最近一次被修改的时间    time_t  st_ctime; //最近一次被更改的时间};
  • 若某一目录具有sticky位(S_ISVTX)则表示在此目录下的文件只能被该文件所有者,此目录所有者或root来删除或改名
  • 对于st_mode包含的文件类型信息,POSIX标准定义的宏
    1. S_ISLNK(st_mode):判断是否为符号链接
    2. S_ISREG(st_mode):一般文件
    3. S_ISDIR(st_mode):目录文件
    4. S_ISCHR(st_mode):字符设备文件
    5. S_ISBLK(st_mode):块设备文件
    6. S_ISFIFO(st_mode):是否为先进先出FIFO
    7. S_ISSOCK(st_mode):socket

int chown(const char *path, uid_t owner, git_t group);
int fchown(int fd, uid_t owner, git_t group)
int lchown(const char *path, uid_t owner, git_t group)

  • chown会将path指定的文件所有者id变为owner代表的用户id,而将文件所有者的组id变更为参数group组id
  • fchown和上面功能一样,只不过以文件描述符作为参数
  • lchown与上面功能一样,在某个文件是符号链接的情况下,lchown更改符号链接本身的所有者id,而不是该符号链接所指向的文件
  • 文件的所有者只能改变文件的组id为其所属组中的一个,超期用户才能修改文件的所有者id
  • 如果owner,group指定为-1,文件的用户id和组id不会被改变
  • 成功返回0,失败-1
  • chown系统调用会清除set-uid位和set-gid 位

int truncate(const char *path, off_t length)
int ftruncate(int fd, off_t length)

  • 将path指向文件大小该为参数length指定的大小,如果原本的文件大小比参数length大,则超过的部分被删除,如果小,则会被扩展,扩展部分以0填充
  • 成功返回0,失败-1

int utime(const char *filename, struct utimbuf *buf)
int utimes(char *fiilename, struct timeval *tvp)

struct utimbuf {    time_t actime;    time_t modtime;};
  • 会吧filenmae指定的文件的存取时间改为buf中的actime,修改时间改为modtime
  • 如果buf为NULL,则将存取时间和修改时间改为当前时间
  • 成功返回0,失败-1

mode_t umask(mode_t mask);

  • umask用于设置文件创建时使用的屏蔽字
  • 参数mask可以直接去数值也可以为open系统调用第三个参数mode的11个宏或他们的组合

文件的移动和删除

int rename(const char *oldpath, const char *newpath)

  • 将oldpath所指定的文件名称修改为newpath所指定的文件名称,若newpath所指定的文件已经存在,则原文件会被删除
  • 成功0,失败-1

int unlink(const char *pathname);
int remove(const char *pathname)

  • remove内部封装了unlink和rmdir
  • unlink从文件系统中删除一个文件,如果文件的链接数为0,且没有进程打开这个文件,则文件被删除且祁占勇的磁盘空间被释放,如果有进程打开这个文件,则文件暂时不删除,知道进程结束。可以确保即使进程崩溃,它所创建的临时文件也不会遗留下俩
  • pathname若指向一个符号链接,则该链接被删除,若指向一个socket,FIFO或这杯文件,该名字呗删除,但已经打开这些文件的进程仍可以使用这些特殊文件
  • 成功返回0,失败-1

目录创建

int mkdir(const char *pathname, mode_t mode)

  • mkdir创建一个新的空目录,目录存取权由mode指定
  • 新创建的目录的uid和创建该目录进程一致,如果附近陈该设置了st_gid位,则新创建的目录页设置st_gid位
  • 成功0,失败-1

目录删除

int rmdir(const char *pathname)

  • 成功0,失败-1
  • 只能删除有pathname指定的空目录

目录其他操作

char *getcwd(char *buf, size_t size)
char *get_current_dir_name(void)
char *getwd(char *buf)

  • getcwd将会把当前的工作目录局对路径复制到buf所指的内存空间,如果size太小,则返回NULL,若buf为NULL,会根据size自动分配内存,如果size也为0,则会自动确定大小,进程可以在使用完释放空间
  • 复制到buf所指定的内存空间,或是返回自动配置的字符串指针,失败返回NULL
  • 如果定义了_GNU_SOURCE,则可使用函数get_current_dir_name获取当前工作目录,自动分配空间来存放路径
  • 如果设置了PWD,则返回PWD的值
  • 如果定义了_BSD_SOURCE或_XOPEN_SOURCE_EXTENDED则也可使用getwd获取当前工作目录。不自动分配内存,buf大小至少为PATH_MAX,getwd仅返回工作目录局对路径字符串的前PATH_MAX个字符

int chdir(const char *path)
int fchdir(int fd)

  • chdir将当前目录改为由参数path指向的目录
  • fchidr将目录改为fd指定的目录
  • chdir实现代码中不允许对path所指向的字符串的内容进行改变
  • 成功0,失败-1

目录打开

DIR *opendir(const char *name)

  • 打开name指定的目录,返回目录流,失败返回NULL

struct dirent *readdir(DIR *dir)

  • 从dir中读取目录项信息
struct dirent {    long d_ino; //目录i节点编号    off_t d_off; //目录文件开头至此目录进入点的位移    unsigned short d_reclean; //d_name的长度    char d_name[NAME_MAX+1]; //文件名,以NULL结尾};
  • 若第一次调用该函数,则返回该目录下第一个文件的信息,第二次调用返回该目录下的第二个文件的信息,一次类推。如果没有返回NULL

目录关闭

int closedir(DIR *dir)

  • 关闭dir指向的目录
  • 成功0,错误-1
0 0