牛客网络编程第一章

第一章

1、静态库制作和使用过程

  • 先得到目标文件

    g++ -c *.cpp
    
  • ar创建库文件

    //xxx为库的名字
    ar rcs  libxxx.a ./*.o
    
  • 生成可执行文件

    //-o 后面为生成的可执行文件名
    //-I 后面为头文件所在位置
    //-L 后面为静态库所在位置
    //-l 后面为静态库名称
    g++ main.c -o main -I ./include/ -L ./lib/ -l xxx
    

2、动态库制作和使用过程

  • 先得到目标文件(与位置无关)

    g++ -c -fpic *.cpp
    
  • 创建动态库文件

    g++ -shared ./*.o -o libsss.so
    
  • 生成可执行文件

    //-o 后面为生成的可执行文件名
    //-I 后面为头文件所在位置
    //-L 后面为动态库所在位置
    //-l 后面为动态库名称
    g++ main.c -o main -I ./include/ -L ./lib/ -l xxx
    

    要配置下动态库的环境变量才可以运行,在home文件夹下的.sshrc中加上下面这行

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:(动态库所在位置)
    

3、静态库和动态库对比

  • 静态库

    • 优点

      • 静态库打包到应用程序速度快

      • 发布程序无需提供静态库,移植方便

    • 缺点

      • 消耗系统资源,浪费内存

      • 更新、部署、发布麻烦

  • 动态库

    • 优点

      • 可以实现进程间资源共享(共享库)

      • 更新、部署、发布简单

      • 可以控制何时加载动态库

    • 缺点

      • 加载速度比静态库慢

      • 发布程序时需要提供依赖的动态库

4、Makefile

  • 文件命名

    makefile或者Makefile

  • 规则

    • 可以有一个规则或多个规则

      目标... :依赖...
      
              命令(shell 命令)
      
              ...
      

      目标:最终要生成的文件(伪目标除外)

      依赖:生成目标所需要的文件或目标

      命令:通过执行命令对依赖操作生成目标(命令前必须Tab缩进)

    • 其他规则都是为第一条规则服务

    • 命令在执行前,需要先检查规则中的依赖是否存在

      • 若存在,执行命令

      • 若不存在,向下检查其他规则,检查有没有一个规则是用来生成这个依赖,若找到,则执行该规则中的命令

    • 检查更新,在执行规则中的命令时,会比较目标进而依赖文件的时间

      • 若依赖的时间比目标的时间晚,则要重新生成目标

      • 若依赖时间比目标的时间早,目标不需要更新,对应规则中的命令不需要被执行

  • 变量

    • 自定义变量

      • 变量名 = 变量值 var = hello
    • 预定义变量

      • AR:归档维护程序的名称,默认为ar

      • CC:C编译器的名称,默认为cc

      • CXX:C++编译器的名称,默认为g++

      • $@:目标的完整名称

      • $<:第一个依赖文件的名称

      • $^:所有的依赖文件

    • 获取变量的值

      • $(变量名)
  • 函数

    • $(wildcard PATTERN…)

      • 功能:获取指定目录下指定类型的文件列表

      • 参数:PATTERN指的时某个或多个目录下的对应的某种类型的文件,如果有多个目录,一般用空格间隔

      • 返回:得到的若干个文件的文件列表,文件名之间使用空格间隔

      • 示例:

        • $(wildcard .c ./sub/.c)

          返回格式:a.c b.c c.c d.c e.c…

    • $(patsubst ,, )

      • 功能:查找 中的单词(单词以空格、Tab、回车、换行分隔)是否符合模式,若匹配,则以替换。

      • 可以包括通配符%,表示任意长度的字符串。若中也包含%,可以用\来转义。

      • 返回:函数返回被替换过后的字符串

      • 示例:

        • $(patsubst %.c, %.o, x.c bar.c)

          返回格式:x.o bar.o
          
  • 最终定义的makefile

    #定义变量
    src= $(wildcard ./*.cpp)
    obj=$(patsubst %.cpp, %.o, $(src))
    target=main
    $(target):$(obj)
            $(CXX) $(obj) -o $(target)
    
    %.o:%.cpp
            $(CXX) -c $< -o $@
    
    .PHONY:clean    //伪目标 不会和外面的clean产生冲突
    clean:
            rm $(obj) -f
    

5、GDB调试

  • 功能

    • 可以启动程序,按照要求运行程序

    • 可以打断点

    • 可以检查断点处的状态

    • 可以修改BUG

  • 注意点

    • 通常会关闭优化选项 -o

    • 打开调试选项 -g

    • 在尽量不影响程序行为的情况下打开所有warning

  • 具体操作

    //-g是在可执行文件中加入源码信息,比如可执行文件中第几条机器指令对应源代码第几行
    //但并不是把整个源文件嵌入到可执行文件中去,所以必须保证gdb能找到源文件
    g++ -g -Wall program.cpp -o program
    
  • 常见命令

    查看信息
    • 启动和退出

      gdb 可执行程序
      quit
      
    • 给程序设置参数/获取设置参数

      set args 10 20
      show args
      
    • GDB使用帮助

      help
      
    • 查看当前文件代码

      list/l  //(从默认位置开始)
      list/l   //行号(从指定的行显示)
      list/l   //函数名(从指定的函数显示)
      
    • 查看非当前文件代码

      list/l   //文件名:行号
      list/l  //文件名:函数名
      
    • 设置显示的行数

      show list/listsize
      set list/listsize //行数
      
    断点相关
    • 设置断点

      b/break 行号
      b/break 函数名
      b/break 文件名:行号
      b/break 文件名:函数
      
    • 设置断点无效

      dis/disable 断点编号
      
    • 设置断点生效

      ena/enable 断点编号
      
    • 设置条件断点(一般用在循环的位置)

      b/break 10 if i==5
      
    • 查看断点

      i/info b/break
      
    • 删除断点

      d/del/delete 断点编号
      
    调试命令
    • 运行GDB程序

      start  (程序停在第一行)
      run    (遇到断点才停) 
      
    • 继续运行,到下一个断点停

      c/continue
      
    • 向下执行一行代码(不会进入函数体)

      n/next
      
    • 变量操作

      p/print 变量名 (打印变量值)
      ptype   变量名 (打印变量类型)
      
    • 向下单步调试(遇到函数进入函数体)

      s/step
      finish (跳出函数体)
      
    • 自动变量操作

      display num (自动打印指定变量的值)
      i/info display  (显示自动变量信息)
      undisplay 编号   (取消自动变量显示)
      
    • 其他操作

      set var 变量名=变量值
      until (跳出循环)
      

6、文件IO

  • 标准C库IO函数
    在这里插入图片描述

  • 标准C库IO和linux系统IO的关系
    在这里插入图片描述

  • 虚拟地址空间
    在这里插入图片描述

  • 文件描述符
    在这里插入图片描述

  • open函数和close函数相关

    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    #include<unistd.h>
    #include<stdio.h>
    
    // 打开一个已经存在的文件
    /*
    int open(const char *pathname,int flags);
    参数设置:
            - pathname:要打开的文件路径
            - flags   :对文件的操作权限设置还有其他设置
                       O_RDONLY, O_WRONLY, O_RDWR 三个设置互斥
    返回值  :
            返回一个新的文件描述符,若调用失败,返回-1
    
    errno:属于Linux系统函数库,是一个全局变量,记录最近的错误号
    
    perror:可以输出错误信息,如下:
    #include<iostream>
    void perror(const char *s);
    作用:用户描述,比如hello,最终输出的内容是  hello.xxx (实际的错误描述)
    */
    
    //
    /*
    int open(const char* pathname,int flags,mode_t mode); 
    参数设置:
            - pathname: 要打开的文件路径
            - flags   :对文件的操作权限设置还有其他设置
                        必选:O_RDONLY, O_WRONLY, O_RDWR 三个设置互斥
                        可选:O_CREAT 文件不存在,则创建
                        flag参数是一个int型的数据,占4个字节,32位
                        flags 32位,每一位就是一个标志位
            - mode    : 创建出新的文件的操作权限(八进制) 如:0777
            最终的权限是:mode & ~umask 即0777 & 0775 = 0775
            umask的作用是抹去某些权限
    返回值  :
            返回一个新的文件描述符,若调用失败,返回-1
    
    */
    int main(){
     int fd = open("create.txt",O_RDWR | O_CREAT,0777);
      if(fd == -1){
          perror("open");
      }
    
      //关闭
      close(fd);
    
      return 0;
    }
    
  • read和write函数

    /*
    #include<unistd.h>
    ssize_t read(int fd,void *buf,size_t count);
    参数:
        - fd : 文件描述符,open得到的,通过这个文件描述符操作某个文件
        - buf:需要读取数据存放的地方,数组的地址(传出参数)
        - count:指定的数组大小
    返回值:
        - 成功:
            >0:返回实际读取到的字节数
            =0:文件读完
        - 失败:-1,并且设置errno
    */
    
    /*
    #include<unistd.h>
    ssize_t write(int fd,const void *buf,size_t count);
    参数:
        - fd : 文件描述符,open得到的,通过这个文件描述符操作某个文件
        - buf:要往磁盘写入的数据
        - count:要写的数据实际大小
    返回值:
        - 成功:返回实际写入的字节数
        - 失败:-1,并且设置errno
    */
    #include<unistd.h>
    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    
    int main(){
    //1、通过open打开文件
        int srcfd = open("./english.txt",O_RDONLY);
        if(srcfd==-1){
            perror("open");
            return -1;
        }
    //2、创建一个新文件(拷贝文件)
        int destfd = open("./cpy.txt",O_WRONLY|O_CREAT,0664);
        if(destfd==-1){
            perror("open");
            return -1;
        }
    //3、频繁地读写操作
        char buf[1024]={0};
        int len = 0;
        while((len = read(srcfd,buf,sizeof(buf)))>0){
            write(destfd,buf,len);
        }
    //4、关闭文件
        close(destfd);
        close(srcfd);
    }
    
  • lseek函数

    /*
    标准c库函数
    #include<stdio.h>
    int fseek(FILE *stream,long offset,int whence)
    
    Linux系统函数
    #include<unistd.h>
    #include<sys/types.h>
    int lseek(int fd,off_t offset,int whence)
    参数:
        - fd :文件描述符,通过open获取,通过这个fd操作某个文件
        - offset : 偏移量
        - whence : 
                SEEK_SET:设置指针偏移量
                SEEK_CUR:设置偏移量--当前偏移量+offset的值
                SEEK_END:设置偏移量--文件大小+offset的值
    作用:
        1、移动指针到文件开始位置 lseek(fd,0,SEEK_SET);
        2、获取当前文件指针的位置 lseek(fd,0,SEEK_CUR);
        3、可以获取文件长度       lseek(fd,0,SEEK_END);
        4、扩展文件长度           lseek(fd,100,SEEK_END);
            注意:要写入数据才生效
    */
    #include<unistd.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<fcntl.h>
    #include<stdio.h>
    
    int main(){
    
        int fd = open("hello.txt",O_RDWR);
    
        if(fd==-1){
            perror("open");
            return -1;
        }
    
        int ret = lseek(fd,100,SEEK_END);
        if(ret==-1){
            perror("lseek");
            return -1;
        }
    
        //必须写入空数据
        write(fd," ",1);
    
        close(fd);
    
        return 0;
    }
    
  • 实战—实现ls - l的功能

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <pwd.h>
    #include <time.h>
    #include <grp.h>
    #include <string.h>
    
    // 模拟实现ls-l
    // 效果:-rwxrwxr-x. 1 wsx  wsx  8889 4月   1 16:24 a.out
    
    int main(int argc, char *argv[])
    {
        // 判断输入参数是否正确
        if (argc < 2)
        {
            printf("%s filename\n", argv[0]);
            return -1;
        }
    
        // 通过stat函数获取用户传入的文件信息
        struct stat st;
        int ret = stat(argv[1], &st);
        if (ret == -1)
        {
            perror("stat");
            return -1;
        }
    
        // 获取文件类型和权限
        char perms[11] = {0}; // 保存文件类型和权限的字符串
    
        switch (st.st_mode & __S_IFMT)
        {
        case __S_IFLNK:
            perms[0] = 'l';
            break;
        case __S_IFDIR:
            perms[0] = 'd';
            break;
        case __S_IFREG:
            perms[0] = '-';
            break;
        case __S_IFBLK:
            perms[0] = 'b';
            break;
        case __S_IFCHR:
            perms[0] = 'c';
            break;
        case __S_IFSOCK:
            perms[0] = 's';
            break;
        case __S_IFIFO:
            perms[0] = 'p';
            break;
        default:
            perms[0] = '?';
            break;
        }
    
        // 判断文件访问权限
        perms[1] = (st.st_mode & S_IRUSR) ? 'r' : '-';
        perms[2] = (st.st_mode & S_IWUSR) ? 'r' : '-';
        perms[3] = (st.st_mode & S_IXUSR) ? 'r' : '-';
    
        // 判断文件所在组
        perms[4] = (st.st_mode & S_IRGRP) ? 'r' : '-';
        perms[5] = (st.st_mode & S_IWGRP) ? 'r' : '-';
        perms[6] = (st.st_mode & S_IXGRP) ? 'r' : '-';
    
        // 其他人
        perms[7] = (st.st_mode & S_IROTH) ? 'r' : '-';
        perms[8] = (st.st_mode & S_IWOTH) ? 'r' : '-';
        perms[9] = (st.st_mode & S_IXOTH) ? 'r' : '-';
    
        // 获取硬连接数
        int linkNum = st.st_nlink;
    
        // 文件所有者
        char *fileUser = getpwuid(st.st_uid)->pw_name;
    
        // 文件所在组
        char *fileGrp = getgrgid(st.st_gid)->gr_name;
    
        // 文件大小
        long int fileSize = st.st_size;
    
        // 获取修改时间
        char *time = ctime(&st.st_mtime);
    
        char mtime[512] = {0};
        strncpy(mtime, time, strlen(time) - 1);
    
        char buf[1024];
    
        sprintf(buf, "%s %d %s %s %ld %s %s", perms, linkNum, fileUser, fileGrp, fileSize, mtime, argv[1]);
    
        printf("%s\n", buf);
    
        return 0;
    }
    
  • 文件属性操作函数

    • access

      /*
      #include<unistd.h>
      int access(const char*pathname,int mode);
      作用:判断某个文件是否有某个权限,或者判断文件是否存在
      参数:
          - pathname:判断文件路径
          - mode    :
                  R_OK:判断是否有读权限
                  W_OK:判断是否有写权限
                  X_OK:判断是否有执行权限
                  F_OK:判断文件是否存在
      返回值:
          -成功返回0
          -失败返回-1
      */
      
      #include <unistd.h>
      #include <stdio.h>
      
      int main()
      {
      
          int ret = access("a.txt", F_OK);
      
          if (ret == -1)
          {
              perror("access");
              return -1;
          }
          printf("文件存在!");
      
          return 0;
      }
      
    • chomd

      /*
      #include<sys/stat.h>
      int chmod(const char*pathname,mode_t mode);
      作用:修改文件权限值
      参数:
          - pathname:文件路径
          - mode    :需要修改的权限值,八进制的数
      返回值:
          -成功返回0
          -失败返回-1
      */
      #include <sys/stat.h>
      #include <stdio.h>
      
      int main()
      {
      
          int ret = chmod("a.txt", 0777);
          if (ret == -1)
          {
              perror("chmod");
              return -1;
          }
      
          return 0;
      }
      
    • chown

      /*
      int chown(const char *path,uid_t owner,gid_t group);
      作用:用来修改所有者和组
      参数:
          路径和用户id和组id
      
      */
      
    • truncate

      /*
      
      #include<unistd.h>
      #include<sys/types.h>
      int truncate(const char *path,off_t length);
      作用:缩减或者扩展文件的尺寸至指定大小
      参数:
          - path :需要修改的文件路径
          - length :需要最终文件变成的大小
      返回值:
          成功返回0
          失败返回-1
      
      */
      
      #include <unistd.h>
      #include <sys/types.h>
      #include <stdio.h>
      
      int main()
      {
      
          int ret = truncate("b.txt", 20);
      
          if (ret == -1)
          {
              perror("truncatm);
              return -1;
          }
      
          return 0;
      }
      
  • 目录操作函数

    • mkdir

      /*
      
      #include<sys/stat.h>
      #include<sys/types.h>
      int mkdir(const char *pathname,mode_t mode);
      作用:创建一个目录
      参数:
          - pathname :创建的目录的路径
          - mode     :权限,八进制的数
      返回值:
          成功返回0
          失败返回-1
      */
      
      #include <sys/types.h>
      #include <sys/stat.h>
      #include <stdio.h>
      
      int main()
      {
      
          int ret = mkdir("aaa", 0777);
      
          if (ret == -1)
          {
              perror("mkdir");
              return -1;
          }
      
          return 0;
      }
      
    • rmdir

      #include <unistd.h>
      #include <stdio.h>
      
      int main()
      {
      
          int ret = rmdir("aaa");
      
          if (ret == -1)
          {
              perror("rmdir");
              return -1;
          }
      
          return 0;
      }
      
    • rename

      /*
      #include <stdio.h>
      int rename(const char *oldpath, const char *newpath);
      */
      
      #include <stdio.h>
      
      int main()
      {
      
          int ret = rename("aaa", "bbb");
      
          if (ret == -1)
          {
              perror("rename");
              return -1;
          }
      
          return 0;
      }
      
    • chdir和getcwd

      /*
      #include <unistd.h>
      int chdir(const char *path);
      作用:修改进程的工作目录
          比如在/home/work下面启动了一个可执行程序a.out,进程的工作目录就是/home/work
      参数:
          - path :需要修改的工作目录
      返回值:
          成功返回0
          失败返回-1
      
      #include <unistd.h>
      char *getcwd(char *buf, size_t size);
      作用:获取当前的工作目录
      参数:
          - buf : 存储的路径,指向的是一个数组(传出参数)
          - size:数组大小
      返回值:
          返回的指向的一块内存,这个数据就是第一个参数
      */
      
      #include <unistd.h>
      #include <stdio.h>
      #include <sys/stat.h>
      #include <sys/types.h>
      #include <fcntl.h>
      
      int main()
      {
      
          // 获取当前工作目录
          char buf[128];
          getcwd(buf, sizeof(buf));
          printf("当前工作目录是:%s\n", buf);
      
          // 修改工作目录
          int ret = chdir("/home/wsx/learn/chapter1/dirFun/temp");
          if (ret == -1)
          {
              perror("chdir");
              return -1;
          }
      
          // 创建新文件
          int fd = open("chdir.txt", O_RDWR | O_CREAT, 0664);
          if (fd == -1)
          {
              perror("open");
              return -1;
          }
      
          // 获取当前工作目录
          char buf1[128];
          getcwd(buf, sizeof(buf1));
          printf("当前工作目录是:%s", buf1);
      
          return 0;
      }
      
  • 目录遍历函数

    /*
    
    #include <sys/types.h>
    #include <dirent.h>
    DIR *opendir(const char *name);
    作用:打开一个目录
    参数:
        - name : 需要打开的目录名称
    返回值:
        DIR + 类型,理解为目录流
        错误返回NULL
    
    
     #include <dirent.h>
    struct dirent *readdir(DIR *dirp);
    作用:读取目录中的数据
    参数:
    
        - dirp : 是opendir返回的结果
    
    返回值:
    
        struct dirent,代表读取到的文件的信息
        读取到了末尾或者失败了,返回NULL
    
    #include <sys/types.h>
    #include <dirent.h>
    int closedir(DIR *dirp);
    作用:关闭目录
    参数:
    
        - dirp : 是opendir的返回值
    
    */
    // #define _DEFAULT_SOURCE
    #include <dirent.h>
    #include <sys/types.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int getFileNum(const char *path);
    // 读取某个目录下所有普通文件个数
    int main(int argc, char *argv[])
    {
    
        if (argc < 2)
        {
            printf("%s path\n", argv[0]);
            return -1;
        }
        
        int num = getFileNum(argv[1]);
        
        printf("普通文件个数位:%d\n", num);
        return 0;
    
    }
    
    // 用于获取目录下所有普通文件的个数
    int getFileNum(const char *path)
    {
    
        // 1、打开目录
        DIR *dir = opendir(path);
        
        if (dir == NULL)
        {
            perror("opendir");
            exit(0);
        }
        
        struct dirent *ptr;
        
        // 记录普通文件个数
        int total = 0;
        
        while ((ptr = readdir(dir)) != NULL)
        {
            // 获取名称
            char *dname = ptr->d_name;
        
            // 忽略.和..
            if (strcmp(dname, ".") == 0 || strcmp(dname, "..") == 0)
            {
                continue;
            }
        
            // 判断是否是普通文件
            if (ptr->d_type == DT_DIR)
            {
                // 目录,需要继续读取这个目录
                char newpath[256];
                sprintf(newpath, "%s/%s", path, dname);
                total += getFileNum(newpath);
            }
            if (ptr->d_type == DT_REG)
            {
                // 普通文件
                total++;
            }
        }
        
        closedir(dir);
        return total;
    
    }
    
    
  • 文件描述符相关操作的函数

    • dup函数

       /*
       #include <unistd.h>
       int dup(int oldfd);
       作用:复制一个新的文件描述符
           fd = 3,int fd1 = dup(fd),
           fd指向的是a.txt,fd1也是指向a.txt
           从空闲的文件描述符中找一个最小的,作为新的最拷贝的文件描述符
       参数:
           - oldfd : 原有的文件描述符
       
       */
       
       #include <unistd.h>
       #include <stdio.h>
       #include <fcntl.h>
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <string.h>
       
       int main()
       {
       
           int fd = open("a.txt", O_RDWR | O_CREAT, 0664);
       
           int fd1 = dup(fd);
       
           if (fd1 == -1)
           {
               perror("dup");
               return -1;
           }
       
           printf("fd:%d , fd1:%d\n", fd, fd1);
       
           close(fd);
       
           char *str = "hello,world!";
           int ret = write(fd1, str, strlen(str));
           if (ret == -1)
           {
               perror("write");
               return -1;
           }
       
           close(fd1);
       
           return 0;
       }
      
    • dup2函数

      /*
       #include<unistd.h>
       int dup2(int oldfd, int newfd);
       作用:重定向文件描述符
           oldfd 指向 a.txt ,newfd 指向 b.txt
           调用函数成功后:newfd 和 b.txt 做 close ,newfd指向了a.txt
           oldfd必须是有效的文件描述符
           oldfd和newfd值相同,相当于什么都没做
       
       */
       
       #include <unistd.h>
       #include <stdio.h>
       #include <string.h>
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <fcntl.h>
       
       int main()
       {
       
           int fd = open("1.txt", O_RDWR | O_CREAT, 0664);
       
           if (fd == -1)
           {
               perror("open");
               return -1;
           }
       
           int fd1 = open("2.txt", O_RDWR | O_CREAT, 0664);
       
           printf("fd: %d, fd1: %d\n", fd, fd1);
       
           int fd2 = dup2(fd, fd1);
       
           if (fd2 == -1)
           {
               perror("dup2");
               return -1;
           }
       
           // 通过fd1去写数据,实际操作的是1.txt,而不是2.txt
           char *str = "hello,dup2";
       
           int len = write(fd1, str, strlen(str));
       
           if (len = -1)
           {
               perror("write");
               return -1;
           }
       
           printf("fd: %d, fd1: %d, fd2: %d\n", fd, fd1, fd2);
       
           // fd2和fd1是相同的
           close(fd1);
           close(fd);
       
           return 0;
       }
      
      
      
      
  • fcntl函数

    /*
    
    #include <unistd.h>
    #include <fcntl.h>
    int fcntl(int fd, int cmd, ... );
    参数:
        -fd : 需要操作的文件描述符
        -cmd: 表示对文件描述符进行如何操作
            - F_DUPED: 复制的是第一个参数fd,得到一个新的文件描述符
                int ret = fcntl(fd,F_DUPED);
            - F_GETFL:获取指定的文件描述符文件状态flag
                获取的flag和我们通过open函数传递的flag是一个东西
            - F_SETFL:设置文件描述符文件状态flag
                必选项:O_RDONLY,O_WRONLY,O_RDWR 不可被修改
                可选性:O_APPEND,O_NONBLOCK
                    O_APPEND    表示追加数据
                    O_NONBLOCK  表示设置成非阻塞
                                (阻塞和非阻塞:描述的是函数调用的行为)
    
    */
    #include <unistd.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
    
        // 1、复制文件描述符
        //  int fd = open("1/txt",O_RDONLY);
        //  int ret = fcntl(fd,F_DUPFD);
    
        // 2、修改或获取文件状态flag
        int fd = open("1.txt", O_RDWR);
        if (fd == -1)
        {
            perror("open");
            return -1;
        }
    
        // 获取文件描述符状态flag
        int flag = fcntl(fd, F_GETFL);
        flag |= O_APPEND;
    
        // 修改文件描述符状态flag,给flag加入O_APPEND这个标记
        int ret = fcntl(fd, F_SETFL, O_APPEND);
        if (ret == -1)
        {
            perror("fcntl");
            return -1;
        }
    
        char *str = "nihao";
        write(fd, str, strlen(str));
        close(fd);
    
        return 0;
    }
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值