linux操作系统软件编程

avatar
作者
筋斗云
阅读量:0

IO(文件) 

文件操作: 

文本文件,mp3,jpeg,png ,mp4,avi

文件:
    一组相关数据的有序集合
文件名:
    这组相关数据的一个名称

linux里面对文件的处理:
思想:
      一切皆文件 ,文件用来存储数据(数据、指令)
      
      everything is file!
      

b c d - l p s 

b -- block      -- 块设备文件   --- 硬盘(存储设备) 
c -- character  -- 字符设备文件 --- 鼠标 
d -- directory  -- 目录文件     
- -- regular    -- 普通文件 
l -- link       -- 软连接文件   --- 类似windows的快捷方式  
p -- pipe       -- 管道文件     --- 实现操作系统中 进程间的一些 信息交换(通信)
s -- socket     -- 套接字文件   --- 网络的时候 (进程间的通信)


【操作文件的基本思路及框架】//凡是文件,都可从这个思路出发进行思考
文件操作三步骤:
1.打开 
2.读写    
3.关闭 

Linux提供的两种文件操作方式:
文件编程:
1.标准IO --- 库函数  -------标准c库函数,
2.文件IO --- 系统调用-------Linux内核为用户提供的函数接口


系统调用:Linux内核为用户提供的函数接口
库函数:标准c库函数, 对Linux内核中系统调用的封装
    


标准IO库:
1.标准io的概念 
    1975 Dennis Ritchie编写, IO库,
    从C语言的标准,ANSI c 
    IO  input  output
    I: 键盘是标准输入设备 ====》

默认输入就是指键盘  /dev/input
    O: 显示器是标准输出设备 ==》默认输出就是指显示器
    
    Linux操作系统当中IO都是对文件的操作
    C一部分,任何支持标准C的系统都可使用标准IO实现文件存储
    标准IO在UNIX上是对文件IO的封装
   
    一般都是对普通文件操作是一种有缓存的IO 在文件IO和用户程序之间,
    加入缓冲区,可以有效减少系统调用的次数,节省系统IO调度资源
    


2.功能:
  用来操作普通文件
      普通文件:
        1.ASCII码文件(代码、文本文件)
        2.二进制文件(音视频、图片)
        
        ASCII码文件是一种特殊的二进制文件
        
        2021
        '2' '0' 2' '1' 
        
        2021
        0000 0000 0000 0000 0000 0111 1110 0101


3.操作方法
    1.打开 -- fopen  //FILE open
    2.读写 --
              fgetc / fputc   读出、写入单个字符
              fgets / fputs   读出、写入一行字符
              fread / fwrite  读出、写入指定长度数据
    3.关闭 -- fclose          


    man手册
    标准man手册分为8个章节:
    man 1        用户命令
    man 2        系统调用
    man 3        c函数库调用
    man 4        设备文件和特殊文件
    man 5        配置文件和格式
    man 6        游戏相关
    man 7        杂项,总述
    man 8        管理类命令

4.API函数接口
 
    1.fopen
    #include <stdio.h>
    FILE* fopen(const char *path, const char *mode);
    功能:
         流打开函数 (打开文件,并关联到一个流)
    参数:
        @path --要打开的文件的文件名(字符串形式)
        @mode --打开文件的操作模式
            r ---打开文件做读操作
                 注意:
                 文件必须存在 
                 
            r+   打开文件做读写操作
                 注意:
                 文件必须存在
                 
            w    打开文件做写操作(写入前清零)
                 注意:
                 如果文件已经存在,则会将文件清空为0
                 如果文件不存在,则会创建一个新文件。
                 
            w+  打开文件做读写操作(写入前清零)
                 注意:
                 如果文件已经存在,则会将文件清空为0
                 如果文件不存在,则会创建一个新文件。

            a    打开文件做写操作(后续写入,不清零)
                 注意:
                 如果文件已经存在,则在文件末尾进行写入 
                 如果文件不存在,则会创建一个新文件。
                 
            a+   打开文件做读写操作(后续写入,不清零)
                 注意:
                 如果文件已经存在,则在文件末尾进行写入 
                 如果文件不存在,则会创建一个新文件。
            
            
    返回值:
       成功 FILE *  (文件流指针)
       失败 NULL 并且 设置 errno 表明错误原因 

       
    流:
        数据从文件当中流入和流出所体现出来的字节流叫做流

        FILE 结构定义的对象(FILE * 指向的对象)称之为流对象,FILE *叫文件流指针。


        标准IO将对文件的操作转换成了对"流"的操作。
        所以,标准IO的文件相关的函数都是围绕着 FILE进行的。
         
          FILE * fp 
          FILE * fp;//流指针------关联一个文件   
          FILE * 实际上是指向了一块内存空间(缓存,fileno)
          
          
          FILE *fp <->【FILE结构体[缓存,fileno]】//堆区(malloc)
 
    2.fclose
      int fclose(FILE *fp);
      功能:
        关闭文件流指针 
      参数:
        fp:文件流指针 
      返回值:
        成功返回0 
        失败返回EOF(-1)
        
      注意:fopen操作完毕后使用fclose关闭,否则会产生内存泄漏
           不要重复调用fclose 
 

    3.fputc
    int fputc(int c, FILE *stream);
    功能:
        向流中写入一个字符
    参数:
        c:要写入的字符
        stream:文件流指针
    返回值:
        成功返回 写入的字符ASCII码值
        失败返回 EOF


    //读 
    4.fgetc
    int  fgetc(FILE *stream);
    功能:
        从流中读取一个字符
    参数:
        stream:文件流指针
    返回值:
        成功返回读到字符的ASCII码值(无符号字符)
        读到文件末尾 返回 EOF   
        失败返回EOF     EOF
        


 
    操作系统在运行一个程序时,会默认打开三个流:
        stdin        FILE*        标准输入流   ---->键盘
        stdout         FILE*        标准输出流   ---->屏幕
        stderr         FILE*        标准出错流   ---->屏幕
    
    gets scanf getchar ->  stdin 
    puts printf putchar -> stdout 
    perror -> stderr 

1.概念
文件io:
    操作系统为了方便用户使用系统功能而对外提供的一组系统函数。
    称之为 系统调用  
    
    其中有一组对文件的操作,称为文件IO
    一般都是对设备文件操作,当然也可以对普通文件进行操作。
    一个基于Linux内核的没有缓存的IO机制
        
        
    
    库函数(标准io):
    1.移植性好
        任何支持标准c库的系统都可以使用标准IO的方式实现对文件的操作,
        不单单是linux上有,在windows,Mac os上都有。
        printf、puts、putchar        
        scanf、gets、getchar
    2.库函数的调用,一般用于应用程序对普通文件的访问
    
    3.库函数本质是对系统调用的封装
        
   系统调用:
    1.操作系统相关,没有跨平台系统的可移植性
        read write 

    2.可以操作普通文件,也可以操作设备文件;通常用于对底层文件的访问
    
    3.发生在内核空间(有空间切换的开销)    
    
        
        
    文件操作:
             缓存           操作对象                具体操作
    标准IO  全缓存/行缓存   文件指针(流指针)FILE *  1.打开 --fopen  
                                                    2.读写 
                                                      fgetc/fputc 
                                                      fgets/fputs 
                                                      fread/fwrite 
                                                    3.关闭 
                                                      fclose 
                                                    4.定位 
                                                      fseek/ftell/rewind 
                                                      
                                                      
                                                      
                                                      
    文件IO  不带缓存        文件描述符 (整数)       1.打开 --open 
                                                    2.读写 --read/write
                                                    3.关闭 --close 
                                                    4.定位 --lseek 
    
        
                
    文件IO特性:
        .1 没有缓存区 (//可以认为数据直接交给了内核 )
        .2 操作对象不在是流(FILE *),而是文件描述符(整数)
        .3文件描述符
          很小的非负的整数    int   0-1023
          内核每打开一个文件就会获得一个文件描述符
          新生成的文件描述符永远为最小的非负整数
          最小未被占用
        
            
          每个程序在启动的时候操作系统默认为其打开
          三个描述符与流对象匹配:
          0 ==>STDIN_FILENO === stdin
          1 ==>STDOUT_FILENO == stdout
          2 ==>STDERR_FILENO == stderr
          
          stdin,stdout,stderr,===>FILE*
          

2.函数接口
        1.open
        int open(const char *pathname, int flags); //打开一个已有文件
        int open(const char *pathname, int flags,int mode);//O_CREAT   + 权限
        功能:
            获得一个文件描述符
        参数:
            pathname:文件名
            flags:
            必须项:他们之间是互斥的,所以有且只能有一个 
                O_RDONLY    
                O_WRONLY    
                O_RDWR      
            可选项:
            O_CREAT  创建文件,若文件存在只作打开操作  //这个标志量存在,则需要指定参数 mode
        
            O_TRUNC  文件内容清空
            O_APPEND 追加方式
            
            //后面
            O_NOCTTY   不是终端设备
            O_ASYNC    异步io,什么时候io不确定,
            O_NONBLOCK 非阻塞 
            
                    
        返回值:
            成功返回文件描述符 (最近最小未使用)
            失败返回-1
                        
            open("1.txt",O_WRONLY|O_CREAT,0666);
            
            最终文件的权限
            ~umask & mode

            r w x  r w x   r w x  
            1 1 0  1 1 0   1 1 0   666   
            1 1 1  1 1 1   1 0 1   ~002 &    1 1 0
            --------------------- 
            1 1 0  1 1 0   1 0 0   664

 
            
        2.close
        int close(int fd);
        功能:
            关闭文件描述符
            
     1.使用文件IO模拟标准IO的所有打开方式
            "r"            O_RDONLY 
            "r+"        O_RDWR 
            "w"            O_WRONLY | O_CREAT | O_TRUNC, 0664
            "w+"        O_RDWR | O_CREAT | O_TRUNC, 0664
            "a"            O_WRONLY | O_CREAT | O_APPEND, 0664
            "a+"        O_RDWR | O_CREAT | O_APPEND, 0664 
     2.用open实现类似touch的命令  
          
    
    
        3.write
        char buf[1024];
        ssize_t write(int fd,  const  void *buf, size_t count);
        功能:
            通过文件描述符向文件中写一串数据
        参数:
            fd:文件描述符
            buf:要写入文件的字符串的首地址
            count:要写入字符的个数
        返回值: 
            成功返回实际写入的个数
            失败返回-1
    
        4.read
        ssize_t read(int fd, void *buf, size_t count);
        功能:
            通过文件描述符读取文件中的数据
        参数:
            fd:文件描述符
            buf:存放数据空间的首地址
            count:要读到数据的个数
        返回值:
            成功返回读到数据的个数
            失败返回-1
            读到文件结尾返回0    

        
        5.lseek  
        off_t lseek(int fd, off_t offset, int whence);
        功能:
            重定位一个文件描述符的偏移量(文件定位器)
        参数:
            fd:文件描述符
            offset:偏移量
                        正:向后偏移
                        负:向前偏移
                        零:不偏移
            whence:
                SEEK_SET
                SEEK_CUR
                SEEK_END
                         正 空洞 
        返回值:
            成功返回当前偏移量的值(off_t   long int)
            失败返回-1 
            
            off_t len =lseek(fd,0,SEEK_END); //获取到文件的大小 
            


注意:
    1、lseek函数执行失败,文件指针还在偏移前的位置。
    2、lseek函数在设备文件上偏移无效。
    3、fifo,socket
 

1.fileno      FILE* fp -> int fd
int fileno(FILE *stream);
功能:
    获得一个文件流指针中的文件描述符
参数:
    stream:文件流指针
返回值:
    成功返回文件描述符
    失败返回-1

2.fdopen    int fd -> FILE *fp
 FILE *fdopen(int fd, const char *mode);
 功能:
    将文件描述符转化为文件流指针
 参数:
    fd:已经打开的文件描述符
    mode:
        "r"
        "r+"
        "w"
        "w+"
        "a"
        "a+"
 返回值:
    成功返回文件流指针
    失败返回NULL   
    
    strtok:
     char *strtok(char *str, const char *delim);
    功能:分割一个字符串
    参数:
         str:要分割的字符串
         delim:分隔符
         
    返回值:
         成功返回分割后的字符串首地址
         失败:NULL
    
    


时间相关函数:

        1.time 
          time_t time(time_t *t);
          功能:
            获得1970年1月1日到现在的秒数 
          参数:
            t:存放秒数空间的首地址
          返回值:
            成功返回1970年1月1日到现在的秒数 (time_t   long)
            失败返回-1 
            
        
          time_t 1970年1月1日到现在的秒数
          日历时间
        
        2.ctime
          char *ctime(const time_t *timep);
          功能:
            将秒数转换为字符串时间
          参数:
            timep:1970年1月1日到现在的秒数
          返回值:
            成功返回时间字符串首地址
            失败返回NULL

        3.localtime
           struct tm *localtime(const time_t *timep);
           功能:
            将秒数转换为时间结构体
           参数:
            timep:存放秒数空间首地址
           返回值:
            成功返回包含时间结构体空间首地址
            失败返回NULL
        
           struct tm {
               int tm_sec;         /* seconds */
               int tm_min;         /* minutes */
               int tm_hour;        /* hours */
               int tm_mday;        /* day of the month */
               int tm_mon;         /* month */
               int tm_year;        /* year */
               int tm_wday;        /* day of the week */
               int tm_yday;        /* day in the year */
               int tm_isdst;       /* daylight saving time */
           };

目录也是文件:


目录文件 ----> 目录流指针 ----> 提供给相关函数操作 

01-打开目录 --opendir
02-读目录   --readdir
03-关闭目录 --closedir 


1.opendir
DIR *opendir(const char *name);
功能:
    打开一个目录获得一个目录流指针
参数:
    name:目录名
返回值:
    成功返回目录流指针
    失败返回NULL

2.readdir
struct dirent *readdir(DIR *dirp);
功能:
    从目录流中读取文件信息并将保存信息的结构体
    地址返回
参数:
    dirp:目录流指针
返回值:
    包含文件信息的结构体
    出错或者读到目录流末尾返回NULL


On Linux, the dirent structure is defined as follows:

       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 */
       };

练习:
    读取目录下的所有文件,打印起inode编号 和名字     


3、关闭目录 
 int closedir(DIR *dirp);
 功能:关闭之前已经打开的目录流对象
 参数:
       opendir的返回结果中目录流对象
 
 返回值:
        成功  0
         失败   -1;
    
    
       DT_BLK      This is a "block device".

       DT_CHR      This is a "character device".

       DT_DIR      This is a "directory".

       DT_FIFO     This is a named "pipe (FIFO)". //管道文件

       DT_LNK      This is a "symbolic link".//软链接 ---相当于是windows的快捷方式 

       DT_REG      This is a regular file.//普通文件 

       DT_SOCK     This is a UNIX domain socket. //socket --- 套接字文件 

       DT_UNKNOWN  The file type is unknown.  //


    

3.chdir

int chdir(const char *path);// /home/linux
功能:
    改变当前程序的工作路径
参数:
    path:改变到的路径
返回值:
    成功返回0
    失败返回-1


4.getcwd //pwd 
char *getcwd(char *buf, size_t size);
功能:
    获得当前的工作路径
参数:
    buf:保存工作路径空间的首地址
    size:保存路径空间的长度
返回值:
    成功返回包含路径空间的字符串首地址
    失败返回NULL

5.mkdir 


int mkdir(const char *pathname, mode_t mode);
功能:
    创建一个目录

参数:
    pathname:路径
    mode: 0777
        mode & ~umask  0002
        
返回值:
    成功返回0
    失败返回-1
    
6.rmdir   rm -rf    rmdir
int rmdir(const char *pathname);
功能:
    删除一个空目录文件
参数:
    pathname:目录文件的名字
返回值:
    成功返回0
    失败返回-1
        
//目录操作:
1.opendir 
2.readdir 
3.closedir 
--------
4.chdir 
5.getcwd 
6.mkdir 
7.rmdir 


 
drwxrwxr-x 2 linux linux 4096 Mar 22 19:31 ./
说明:
 
    d     rwx rwx r-x     2        linux  linux  4096       Mar 22 19:31      ./
文件类型  相关权限   目录          所有者 所在组 文件大小  最后被修改的时间    文件名
          用户        (子目录个数)
          所在组     文件
          其他人      (硬链接数)
          (用户组)
          
---------------------------
1. Linux文件系统:
    目录项:文件名  inode
    inode表:inode号, 文件大小  类型   指示
    数据块:文件内容

        1.软连接:符号链接
            1.占用内存空间
            2.可以链接目录
            3.删除软链接源文件无影响,删除源文件,软链接失效

            创建:
            ln -s 源文件名  软链接名


        2.硬链接:文件别名(inode)

            1.目录不能有硬链接
            2.硬链接不占空间
            3.当硬链接数为0时,此文件才被删除

            创建:

            ln  源文件名   硬链接文件名

        3.symlink
          int symlink(const char *target, const char *linkpath);
          功能:创建软连接
          参数:
                target     源文件
                linkpath   链接文件
                
        4.link
         int link(const char *oldpath, const char *newpath);
         功能:创建硬链接 
         参数:
                oldpath  源文件
                newpath  链接文件
        5.readlink
          ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);
          功能:读软链接文件(获得软链接文件指向的文件名)
          参数:
                pathname  软连接文件
                buf       存放链接文件的空间
                bufsiz    buff的大小
---------------------------

ls -l
2. 文件属性的获取

       int  stat(const char *path, struct stat *buf);
       int fstat(int           fd, struct stat *buf);
       int lstat(const char *path, struct stat *buf);  
           //软链接 --- lstat  获取软链接这个链接文件本身的属性信息,而不是连接到的目标文件的属性信息。
    

        stat
        int  stat(const  char  *path, struct stat *buf);
        功能:
            获得文件的属性
        参数:
            path: 文件的路径
            buf:  属性存放空间的首地址
        返回值:
            成功返回0
            失败返回-1
       
       
       All of these system calls return a stat structure, which contains the following fields:

           struct stat {
               dev_t     st_dev;     /* ID of device containing file */
               ino_t     st_ino;     /* inode number */(*)
               mode_t    st_mode;    /* protection */(* 权限信息)
               nlink_t   st_nlink;   /* number of hard links */(* 硬链接数)
               uid_t     st_uid;     /* user ID of owner */ (*UID 用户id)
               gid_t     st_gid;     /* group ID of owner */(*group 所在组ID)
               dev_t     st_rdev;    /* device ID (if special file) */
               off_t     st_size;    /* total size, in bytes */(*文件的大小)
               blksize_t st_blksize; /* blocksize for file system I/O */
               blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
               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 */(*最后的状态改变的时间)
           };


       The following flags are defined for the st_mode field:

           S_IFMT     0170000   bit mask for the file type bit fields
           S_IFSOCK   0140000   socket
           S_IFLNK    0120000   symbolic link
           S_IFREG    0100000   regular file
           S_IFBLK    0060000   block device
           S_IFDIR    0040000   directory
           S_IFCHR    0020000   character device
           S_IFIFO    0010000   FIFO
            //---------------------------------------------------------------
           S_ISUID    0004000   set UID bit
           S_ISGID    0002000   set-group-ID bit (see below)
           S_ISVTX    0001000   sticky bit (see below)
           //---------------------------------------------------------------
           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
           
           
           
           
           0 000 1
           0 000 2
           0 000 4
           000 ---- 100
           000 ---- 010 
           000 ---- 001

st_mode标志位

     000 000 000 100 000 000
     001 100 110 0

 000 000  000    000 000 000
|文件   | |设置| |文件权限 |  
|类型   | |组和|
          |用户|
          |ID  |
          
4.Linux用户相关函数        
        // /etc/passwd
        1.getpwuid
          struct passwd *getpwuid(uid_t uid);
          功能:
            获得uid对应用户信息
          参数:
            uid:用户的ID号 
          返回值:
            成功返回包含用户信息的结构体地址
            失败返回NULL
        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 */
        };    

        // /etc/group
        2.getgrgid
          struct group *getgrgid(gid_t gid);
          功能:
            根据组ID获得组信息
          参数:
            组ID
          返回值:
            成功返回组信息结构体指针
            失败返回NULL
        
        struct group {
           char   *gr_name;       /* group name */
           char   *gr_passwd;     /* group password */
           gid_t   gr_gid;        /* group ID */
           char  **gr_mem;        /* group members */
        };
        

4.linux下时间的获取
            
        1.获取秒数    --time() 秒数 
        2.转换为需要个格式    ()      
        系统时间的获取:
        1.time
        time_t time(time_t *t);
        time_t tm;
        time(&tm)

        tm = time(NULL);
        功能:
            获得1970年到现在的秒数
        参数:
            t:存放秒数的空间首地址
        返回值:
            成功返回1970年到现在的秒数
            失败返回-1

        2.localtime
        struct tm *localtime(const time_t *timep);
        功能:
            将一个秒数转化成日历时间
        参数:
            timep:保存秒数空间的地址
        返回值:
            成功返回保存日历时间结构体的指针
            失败返回NULL

        3.ctime
        char *ctime(const time_t *timep);//date
        功能:
            将时间秒数转化成字符串
        参数:
            timep:保存时间空间的地址
        返回值:
            成功返回获得时间字符串的首地址
            失败返回NULL

         struct tm 
         {
        int tm_sec;         /* seconds */
        int tm_min;         /* minutes */
        int tm_hour;        /* hours */
        int tm_mday;        /* day of the month */
        int tm_mon;         /* month */
        int tm_year;        /* year */
        int tm_wday;        /* day of the week */
        int tm_yday;        /* day in the year */
        int tm_isdst;       /* daylight saving time */
        };

        

    广告一刻

    为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!