3.系统调用函数,对文件的操作

系统调用:
定义:操作系统把它具有的功能列成一张表,然后给每一个功能取一个编号,当用户层需要调用某个系统功能时,只需要向内核发送对应的编号即可。
 1.Linux和Unix系统的绝大多数功能都是通过系统调用形式提供的,不是通过函数形式调用,当需要执行这些功能的时候,可以向内核发送一个编号,那么内核就会把对应的系统调用执行。
 2.系统调用是以标准C语言的形式提供的,但是它不属于C语言.
 3.一般程序员所写的代码都工作在用户态,但系统调用工作在内核态,用户态是不能直接访问内核中的数据,必须经过系统调用才行。
一切皆文件
 在Unix和Linux系统中基本上把所有的资源都抽象成了文件,包括网络,打印机,串口,鼠标键盘,显示器,都可以像操作文件一样来控制硬件
 文件分类:
  目录文件
  设备文件 /dev
  普通文件
 一般操作文件需要的操作
  打开 读 写 设置 关闭
常见的文件相关的系统调用

文件描述符:是一个非负的整数,功能类似于标准C中的FILE*文件指针,它代表内核中一个打开的文件


 打开文件
     int open(const char *pathname, int flags);
     pathname:文件的路径
     flags:
      O_RDONLY 只读
      O_WRONLY 只写
      O_RDWR 读写
      O_CREAT 创建
      O_EXCL 文件已存在,则创建失败
      O_NOCTTY
      O_TRUNC 打开时是否清空
      O_APPEND打开时以追加的方式打开
     返回值:
      文件描述符,是一个无符号整数,这个整数对应一个内核对象,对程序来说它的值是多少无所谓,把它当作操作文件的令牌即可。
      特殊的文件描述符:
       0 标准输入
       1 标准输出
       2 标准错误
         int open(const char *pathname, int flags, mode_t mode);
         mode是用来给文件设置权限的,但是通过mode设置的权限会被权限屏蔽码过滤,权限设置是以八进制方式设置的。
          umask设置,查看权限屏蔽字的
    关闭文件:
        int close(int fd)
        fd:文件描述符
        返回值:0表示成功,1表示失败
    创建文件:
     int creat(const char *pathname,mode_t mode);//底层调用的是open
      pathname:文件路径
      mode:文件权限,会受到文件屏蔽字的过滤,创建文件时候需要设置文件权限 0mmm
      creat是调用open来实现的
      返回值:文件描述符
    写文件:
     ssize_t write(int fd, const void *buf, size_t count);
      fd:文件描述符
      buf:要写入的首地址
      count:希望写入的字节数
      返回值:实际写入的字节数
    读文件:
     ssize_t read(int fd, void *buf, size_t count);
      fd:文件描述符
      buf:数据存放的位置
      count:希望读入的字节数
      返回值:实际读入的字节数
     练习:实现cp命令。
文本文件的数据读写
 1.结构体以文本形式写入文件中
  a.准备缓存区
  b.把结构体使用sprintf拼接到缓冲区中
  c.把缓冲区里的内容写入文件
 2.从文本文件中读取结构体
  a.准备缓冲区
  b.把数据从文件中读取到缓冲区中
  c.使用sscanf从缓冲区中解析结构变量
文件位置指针:
 off_t lseek(int fd, off_t offset, int whence);
 fd:文件描述符
 offset:偏移值
 whence:基准值
 返回值:调整后的文件位置指针所在的位置
 lseek 对应 fseek
 ftell 没有对应,lseek(fd,0,SEEK_CUR);就可以实现这个功能,rewind同理
 文件黑洞:lseek是可以把文件位置指针调整到文件的末尾之后的位置,形成的空白的东西叫做文件黑洞,文件黑洞是没有数据的,也不占用硬盘空间,但是回计算在文件大小中。
标准IO与系统IO
 例子:把所有short的值写入到文件中
 标准IO在进行数据读写时,不会把数据直接写入到文件中,而是先写入缓冲区,减少了进出内核的速度,这样就大大提高了文件的读写速度。
 系统IO在不使用缓冲区的情况下,速度不如标准IO。因此在使用系统IO读写文件时一定要为它分配一块缓冲区,大小最好为一页(4K/4096byte)。




文件描述符的复制:
 #include <unistd.h>
 int dup(int oldfd);
 oldfd:想要复制的文件描述符
特殊的几个描述符:
0 = STDIN_FILENO
1 = STDOUT_FILENO
2 = STDERR_FILENO
 返回值:最小的没有使用过的文件描述符
    int dup2(int oldfd, int newfd);
    oldfd:想要被复制的文件描述符
    newfd:指定的文件描述符,如果已经被占用则关闭,再复制



fcntl
    1.复制文件描述符
    2.获取文件权限
    3.设置文件的权限
    4.用此函数操作硬件设备时,fcntl的功能是由硬件驱动决定的,功能可以自定义


文件同步
    sync 同步所有打开的文件到磁盘
    fsync 同步指定的文件到磁盘
    fdatasync 同步指定的文件,但是只同步数据


umask/access
    设置权限屏蔽码,只对当前进程有效
    access 查询文件的权限
        F_OK
        R_OK
        W_OK
        X_OK


chmod/fchmod/chown/fchown/lchown
    chmod/fchmod 修改文件的权限
    chown/fchown/lchown 修改用户id和组id
        lfunc只对软连接文件有效,不针对目标


truncate/ftruncate
    文件的截取,把文件多余的内容去掉


link/unlink/remove
    link创建链接文件,创建的是硬链接
    unlink珊瑚链接,一个普通文件其实就是一块数据区,对应了一个硬链接,当一个文件的链接数减为0的时候这个文件就被删除了,此函数也可以用来删除文件。
    remove用来删除文件,与unlink功能类似
    rename重命名

symlink/readlink
    symlink 创建软链接
    readlink 读取软链接
        而使用open打开软链接文件,打开的是它的链接目标,所以读取到的不是链接文件的内容


mkdir/rmdir
    mkdir创建目录,创建的目录要有执行权限,否则无法打开
    rmdir只能用来删除空目录,操作系统没有提供删除非空目录的系统调用。
    练习:实现rm -rf的功能


目录流的操作
    opendir/fopendir 打开一个目录流 返回DIR*
    readdir    从目录流中读取一个对象 struct dirent*
    closedir 关闭目录流

    seekdir  设置目录流位置
    telldir    返回当前目录流的位置
    rewinddir 把目录流的位置调整到开头


    struct dirent {
               ino_t d_ino; /* inode number */
               off_t d_off; /* offset to the next dirent */
               unsigned short d_reclen; /* length of this record */
               unsigned char d_type; /* type of file; not supported
                                              by all file system types */
               char d_name[256]; /* filename */
           };





    练习:实现ls -l的功能
  




获取用户组信息getpwuid/getgrgid
    getpwuid:使用用户ID获取用户信息
    struct passwd *getpwuid(uid_t uid);

    struct passwd { 
               char *pw_name; /* username */
               char *pw_passwd; /* user password */
               uid_t pw_uid; /* user ID */
               gid_t pw_gid; /* group ID */
               char *pw_gecos; /* user information */
               char *pw_dir; /* home directory */
               char *pw_shell; /* shell program */
           };


    getgrgid:使用组ID获取组信息
    struct group *getgrgid(gid_t gid);

    struct group {
               char *gr_name; /* group name */
               char *gr_passwd; /* group password */
               gid_t gr_gid; /* group ID */
               char **gr_mem; /* group members */
           };


练习
        



附件列表

     

    posted @ 2018-07-24 20:04  LyndonMario  阅读(633)  评论(0编辑  收藏  举报