系统IO

系统IO: 不带缓冲的IO,其是基于标准IO所设计的!

    1、打开/关闭函数
        头文件:
        #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);
        功能:打开一个文件并返回这个文件的描述符
            文件描述符:就是文件表项的下标 文件表项就是一个矢量 即数组!
                        数组中存储了文件描述符和文件指针!文件描述符本质就是这个文件指针在数组中的下标!
        参数:pathname:带路径的文件名
                flags:打开文件的标志,可以使用位或的我形式添加一下成员:
                    O_WRONLY :只写权限
                    O_RDONLY :只读权限
                    O_RDWR    :可读可写权限
                    以上三个标志必须并且只能选择其中一个!
                    可以位或一下几个:
                    O_APPEND :追加方式 写数据到文件末尾
                    O_CREAT :创建标志,如果文件不存在就创建,存在则打开。
                    O_EXCL :该标志一般与O_CREAT一起使用,用来测试文件是否存在,如果存在且是一个普通文件则报错,
                            如果不存在则创建!
                    O_NONBLOCK :非阻塞方式打开文件
                        关于阻塞和非阻塞学习第二阶段进程时会讲!
                    O_TRUNC : 截断标志 假如文件存在且是一个普通文件,而且打开的方式是O_RDWR 或者
                            O_WRONLY,那么文件就会被清空!
                前两个参数是第一个open函数和第二个函数共有的参数,第三个参数只有当第二个参数flags中有
                O_CREAT 时才有意义:
                mode :打开创建文件的权限:有两种方式确定!
                1、使用以下的固定宏 以下宏可以位或使用
                S_IRWXU  00700 user (file owner) has  read,  write  and  execute
                   permission
                    文件所有者可读可写可执行权限
                S_IRUSR  00400 user has read permission
                    文件所有者可读的权限
                S_IWUSR  00200 user has write permission
                    文件所有者可写权限
                S_IXUSR  00100 user has execute permission
                    文件所有者可执行的权限
                S_IRWXG  00070 group has read, write and execute permission
                    用户所在组可读可写可执行
                S_IRGRP  00040 group has read permission

                S_IWGRP  00020 group has write permission

                S_IXGRP  00010 group has execute permission

                S_IRWXO  00007 others have read, write and execute permission
                    其他用户权限
                S_IROTH  00004 others have read permission
                
                S_IWOTH  00002 others have write permission

                S_IXOTH  00001 others have execute permission
                2.通过8进制形式指定
                    0     八进制                 八进制             八进制·
                        文件所有者权限        用户组权限        其他用户权限
                        1 1 1
                        r w x 分别对应一个八进制位,只要该位为1,即拥有此权限!
                    
                    ex:0710 意思是什么? 所有可读可写可执行,用户组可执行 其他用不可写不可读不可执行!
        返回值:成功返回一个非负数即文件描述符,失败返回-1;错误存放在errno!
        
        关闭文件:
            #include <unistd.h>
            函数原型    int close(int fd);
            参数:fd open的返回值,即一个文件描述符
            返回值: 成功返回0 失败返回-1;
    2、读写一个文件:
        读取:
             #include <unistd.h>

            ssize_t read(int fd, void *buf, size_t count);
            功能:从文件描述符fd所指的文件中读取count个字节的数据到buf所指的内存中!
            参数: fd 文件描述符 open的返回值!
                    buf 存储读取数据的内存的首地址
                    count 读取数据的大小!
            返回值:成功返回读取到数据的字节数,失败返回-1;
                返回值 与 count的关系是什么? 返回值<=count!
                
                返回值: 
                    >0说明读取到了数据 并且数据大小就是 返回值的大小
                    =0 说明文件已经读完了!
                    <0 说明出错了!
        写: 
        #include <unistd.h>

       ssize_t write(int fd, const void *buf, size_t count);
       功能:将buf所指的内存中的count个字节的数据写入到fd这个文件中!
       参数:fd 文件描述符 open的返回值!
                    buf 存储写入数据的内存的首地址
                    count 写入数据的大小!
        返回值: 成功返回 成功写入数据的大小
                失败返回 -1;
            返回值 与count 的关系? 返回值<=count!
            >0 :说明写入了返回值大小的数据
            =0 :说明什么东西都没写进去!
            <0 :写入失败!最典型的写入失败就是没有权限操作时的写入!
    
    作业:使用系统IO实现cp指令!
    
    3、定位
        lseek:
         #include <sys/types.h>
       #include <unistd.h>

       off_t lseek(int fd, off_t offset, int whence);
        参数:fd 文件描述符 
            offset 偏移量
            whence 从哪里开始偏移 有以下三个取值
                1、SEEK_SET 从文件头开始偏移 此时 offset只能为正
                2、SEEK_END 从尾巴开始偏移
                3、SEEK_CUR 从当前位置开始偏移 偏移量可正可负 正为向后偏移 负为向前偏移!
            返回值:成功返回当前光标位置相对于文件头的距离!
                    失败返回-1!
        写一个函数求文件的大小!
    4、删除一个空目录或者普通文件    
        remove
        #include <stdio.h>

       int remove(const char *pathname);
        功能:删除一个普通文件或空目录
        参数:带路径的文件名或空目录名!
        返回值:成功返回0 失败返回-1;
    
    作业:实现mv指令:
        移动或者重命名文件的!
        注意:区别移动还是重命名!如何区别?此时我们先用文件后缀名来区别!如果后缀名
        相同则为重命名,不同则为移动!
        mv 实现: cp + remove
        
    5、获取文件属性即文件信息和状态《小写的LL能查看当前目录下所有文件的状态信息》
         #include <sys/types.h>
       #include <sys/stat.h>
       #include <unistd.h>

       int stat(const char *path, struct stat *buf);
        int fstat(int fd, struct stat *buf);
       int lstat(const char *path, struct stat *buf);
       功能:
        stat 用来将path指定的文件的信息和状态保存到buf 所指的内存空间中!
        fstat 与stat函数类似,其试讲fd这个已经打开的文件的信息和状态保存到buf所指的内存空间!
        lstat 与stat函数类似,只不过,当path符号链接的时候,获取的是链接本身的状态和信息,而不是他所指的
                文件,也就是说stat函数观察不到符号链接的状态,要使用lstat函数观察!
                符号链接: 就是软连接 其实就是一个快捷方式!
                硬链接: 其实就是一个备份!
        参数: path 带路径的文件名!也可以是路径
                如果linux库函数中见到path 指的就是路径 也可以是带路径的文件!
                如果见到 pathname 一定是带路径的文件名!不能是路径!
                fd 文件描述符 使用open打开文件的返回值!
                buf 类型是 struct stat * 结构体指针,这个执行执行一个结构体是用来保存文件状态信息的!
                 struct stat {
                       dev_t     st_dev;     /* ID of device containing file */ 文件的设备编号
                       ino_t     st_ino;     /* inode number */ i节点号 
                       mode_t    st_mode;    /* protection */ 文件的类型或者存储权限
                       nlink_t   st_nlink;   /* number of hard links */ 链接到该文件的硬链接数目,刚建立该文件是为1!
                       uid_t     st_uid;     /* user ID of owner */ 文件所有者的编号
                       gid_t     st_gid;     /* group ID of owner */ 文件所有者所在组的编号
                       dev_t     st_rdev;    /* device ID (if special file) */ 如果该文件是一个设备文件,则是设备编号!
                       off_t     st_size;    /* total size, in bytes */ 文件大小 单位是字节
                       blksize_t st_blksize; /* blocksize for filesystem I/O */ IO文件系统的缓冲区大小
                       blkcnt_t  st_blocks;  /* number of 512B blocks allocated */ 占用文件区块的个数,每个区块大小为512个字节
                       time_t    st_atime;   /* time of last access */ 最后一次存取的时间
                       time_t    st_mtime;   /* time of last modification */ 最后一次修改的时间
                       time_t    st_ctime;   /* time of last status change */ 最后一次更改权限或者用户状态(用户所有者)的时间
                   };

                重点要看到的是st_mode这个成员:
                    这个成员变量包含了文件的权限和文件类型!
                    文件权限通过位与的形式得到
                        S_IRWXU    00700     mask for file owner permissions
                        S_IRUSR    00400     owner has read permission
                        S_IWUSR    00200     owner has write permission
                        S_IXUSR    00100     owner has execute permission
                        S_IRWXG    00070     mask for group permissions
                        S_IRGRP    00040     group has read permission
                        S_IWGRP    00020     group has write permission
                        S_IXGRP    00010     group has execute permission
                        S_IRWXO    00007     mask for permissions for others (not in group)
                        S_IROTH    00004     others have read permission
                        S_IWOTH    00002     others have write permission
                        S_IXOTH    00001     others have execute permission
                        一般不怎么常用,就是在做文件系统时要考虑!
                    文件的类型是通过以下的宏定义得出的:
                        S_ISREG(m)  is it a regular file?
                            如果这个宏的真值为1 就说明这个文件是一个普通文件!
                        S_ISDIR(m)  directory?
                            如果这个宏的真值为1则说明该文件是一个目录文件,就是一个文件夹!
                        S_ISCHR(m)  character device?
                            如果这个宏的真值为1则说明该文件是一个字符设备文件:学驱动的时候会将!
                        S_ISBLK(m)  block device?
                            如果这个宏的真值为1 则说明该文件是一个块设备文件
                        S_ISFIFO(m) FIFO (named pipe)?
                            如果这个宏的真值为1 则说明该文件是一个管道文件,在学习进程间通信是会讲!
                        S_ISLNK(m)  symbolic link?  (Not in POSIX.1-1996.)
                            如果这个宏的真值为1则说明该文件是一个软连接文件,这个再1996年之前的系统中没有!
                        S_ISSOCK(m) socket?  (Not in POSIX.1-1996.)
                            如果这个宏的真值为1则说明该文件是一个网络文件,这个再1996年之前的版本中也没有!
                        以上宏中的m就是st_mode的值!
            返回值:成功返回0,失败返回-1;错误存放在errno!
                错误编号解析:
                    ENOENT 参数path指定的文件或目录不存在!
                    ENOTDIR 参数path所指的目录存在,但不是一个真正的目录!
                    ELOOP 准备打开的文件有过多的符号链接问题,一个设备或者文件最多能有多少个符号链接?上限为16个
                    EFAULT 参数buf是一个无效的指针,指向了非法的区域!比如buf指向.rodata区!
                        char *p = "123456";
                        *p = 'a';对吗? 不对!原因是 p是一个指针,指向一个字符串的首地址!这个字符串存放在常量区!
                        
                        char q[] = "123456";
                        *q = 'a';对吗?对,原因是q是一个字符数组,修改该数组中的第一个成员是合法的!

       练习:mv指令实现判断重命名和移动的方式使用stat来实现!发邮箱!
       
    6、目录结构和目录操作
        linux底下用小写LL能查看当前目录下所有的文件状态。
        1、创建和删除一个目录!
            #include <sys/stat.h>
            #include <sys/types.h>

            int mkdir(const char *pathname, mode_t mode);
            参数: pathname 带路径的文件名,(在linux下所有东西都是文件)
                    mode 同open的mode 有两种方式确定!
                    1、使用以下的固定宏 以下宏可以位或使用
                    S_IRWXU  00700 user (file owner) has  read,  write  and  execute
                       permission
                        文件所有者可读可写可执行权限
                    S_IRUSR  00400 user has read permission
                        文件所有者可读的权限
                    S_IWUSR  00200 user has write permission
                        文件所有者可写权限
                    S_IXUSR  00100 user has execute permission
                        文件所有者可执行的权限
                    S_IRWXG  00070 group has read, write and execute permission
                        用户所在组可读可写可执行
                    S_IRGRP  00040 group has read permission

                    S_IWGRP  00020 group has write permission

                    S_IXGRP  00010 group has execute permission

                    S_IRWXO  00007 others have read, write and execute permission
                        其他用户权限
                    S_IROTH  00004 others have read permission
                    
                    S_IWOTH  00002 others have write permission

                    S_IXOTH  00001 others have execute permission
                    2.通过8进制形式指定
                        0     八进制                 八进制             八进制·
                            文件所有者权限        用户组权限        其他用户权限
                            1 1 1
                            r w x 分别对应一个八进制位,只要该位为1,即拥有此权限!
            返回值:成功返回0 失败返回-1,错误存放在errno中!            

            删除一个目录      
            #include <unistd.h>
            int rmdir(const char *pathname);
            参数:要删除的目录名,成功返回0 失败返回-1;
        
        2、打开一个目录:
              #include <sys/types.h>
           #include <dirent.h>

           DIR *opendir(const char *name);
           DIR *fdopendir(int fd);
            参数:name 要打开的目录名称!
                  fd 打开的目录文件描述符!
            返回值:成功返回目录指针,失败返回NULL;
            
            目录指针:实质是一个指针,指向一个目录!
            
            关闭一个目录
             #include <sys/types.h>
           #include <dirent.h>
           int closedir(DIR* drip);
        3、读取目录
             #include <dirent.h>

            struct dirent *readdir(DIR *dirp);
            参数:从dirp指向的目录中,读取下一个目录项!一般为opendir的返回值!
            返回值:成功返回读取到目录的地址,并将目录指针指向下一个目录项!失败返回NULL!
            
            目录信息结构体:
              struct dirent {
               ino_t          d_ino;       /* inode number */ i 节点号
               off_t          d_off;       /* not an offset; see NOTES */ 在目录文件中的偏移量!
               unsigned short d_reclen;    /* length of this record */文件名的长度
               unsigned char  d_type;      /* type of file; not supported
                                              by all filesystem types */  文件的类型
               char           d_name[256]; /* filename */ 文件名
            };
            如何实现ls?
                ls 是干嘛的?列举当前文件下所有的文件的!
                    先实现一个不带参数的!
                    第一步打开目录 
                    读目录 读一个打印其中一个的名字!
                    
            如何实现带参数的ls!
                linux 下 以.开头的文件都是隐藏文件!

        4、改变当前工作路径
             #include <unistd.h>

           int chdir(const char *path);
           int fchdir(int fd);
           参数:目标路径
        5、获取当前工作路径
                #include <unistd.h>
               char *getwd(char *buf);
               参数 :保存的路径名!
            getwd 该函数会报一个与gets一样的警告,原因是该函数不会检测 buf是否越界!
            

    作业:
        1、实现完整的mv指令 方法已经讲过了!先复制 再删除 然后注意区分是重命名还是移动!
            如果是移动则第二个参数就是一个目录文件 此处就可以做了!
        2、使用递归实现目录的打印,注意跳过当前目录和上一级路!
        这两道题目发邮件!2452476922@qq.com!    

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值