• Day4:Linux系统编程1-60P


    我的学习方法是:Linux系统编程(看pdf笔记) + Linux网络编程 + WebServer

    01P-17P Linux相关命令及操作

    • cp -a dirname1 dirname2 复制目录

      cp -r dirname1 dirname2 递归复制目录 1 到目录 2

      这里-a 和-r 的差别在于,-a 是完全复制,文件权限,改动时间什么的也完全相同。

    • more filenamecat 差不多,但是对于大文件查看很强势

    • head -n filename 查看文件前 n 行

    • tail -n filename 查看文件后 n 行

    • ln -s file file.s 创建一个软链接(相当于win的快捷方式),最好使用绝对路径

    • ln file file.h 创建一个硬链接,文件和硬链接的 Inode 是相同的,每个文件都有唯一的 Inode(硬链接一改都改,类似于cpp的引用)

    • find命令 -type按种类,-name按名字

    • grep 命令:找文件内容 ,与ps配合使用ps aux | grep 'cupsd'

    • gzip 和 bzip2 都是压缩命令,配合tar使用,rar压缩需要安装rar。

    • ifconfig查看网卡信息

    18P - 24P Vim相关(一刷不看)

    25P-27P gcc相关

    • gcc中间文件及步骤:

    image

    28P-37P 动态库和静态库

    • 静态和动态的优劣:静态库在文件中静态展开,所以有多少文件就展开多少次,非常吃内存,但是这样的好处就是静态加载的速度快;使用动态库会将动态库加载到内存,10 个文件也只需要加载一次,然后这些文件用到库的时候临时去加载,速度慢一些,但是很省内存。如何理解动态和静态:静态的写在源代码里的函数,相对 main 函数偏移是一定的,链接时,回填 main 函数地址之后,其他源代码 里的函数也就得到了地址,动态则用plt代替,之后加载的时候再替换掉 )
    • 编译器只能隐式声明返回值为 int 的函数形式:int add(int ,int ); 如果函数不是返回的 int,则隐式声明失效,会报错:在使用自己编写的静态库时,需要在Main中加入函数声明 。但这个方法需要库的使用者知道库里的函数,完事儿一个一个加到代码里,不太行,解决方法:使用头文件加载静态库:这样防止多次展开静态库带来额外开销。

    image

    38P-40P GDB调试(跳过)

    41P-46P Makefile(跳过)

    47P-51P 系统调用open

    • 系统调用是内核提供的函数,库调用是程序库中的函数;
    • open() 函数出错时,程序会自动设置 errno,可以通过 strerror(errno)来查看报错数字的含义 以打开不存在文件为例(如果成功fd会返回打开文件所得到对应的 文件描述符)

    image

    52P-53P 系统调用read/write(复制命令)

    • 系统调用(write/read)和库函数调用(fgetc/fputc)的区别:read每次写n个字节,会疯狂进行内核态和用户态的切换,所以非常耗时。fgetc/fputc,有个缓冲区,预读入缓输出机制。

    54P 文件描述符

    • 文件描述符是指向一个文件结构体的指针
    • 在Linux中,文件描述符是一个非负整数,用于标识一个进程正在使用的文件或者其他输入/输出资源。每个进程都有一个文件描述符表,其中存储了该进程打开的文件描述符。标准输入、标准输出和标准错误输出分别使用文件描述符0、1和2。其他文件描述符从3开始递增。文件描述符可以用于读取、写入、关闭文件以及进行其他文件操作。标准输入输出一般指的就是键盘输入/输出;

    55P 阻塞和非阻塞

    • 阻塞/非阻塞是设备文件、网络文件的属性(常规文件没有阻塞的概念)。
    • 比如读取dev/tty (这也是个文件),如下写法就是阻塞的:
    /* 使用阻塞的read读取终端(标准输入输出)*/
    #include 
    #include 
    #include 
    
    int main(){
        char buf[10];
        int n;
         
        n = read(STDIN_FILENO, buf, 10);
        if(n < 0){
            perror("read STDIN_FILENO");
            exit(1);
        }
        write(STDOUT_FILENO, buf, n);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    56P-57P 系统调用fcntl

    • fcntl(file control)是一个系统调用,用来改变一个【已经打开】的文件的访问控制属性
    • 函数声明int fcntl(int fd, int cmd, ... /* arg */ ); cmd表示命令,比如下面这句代码将阻塞改为非阻塞:其中F_SETFL设置,F_GETFL获取
        flags = fcntl(STDIN_FILENO, F_GETFL); //获取 stdin 属性信息
        if(flags == -1){
            perror("fcntl error");
            exit(1);
        }
        flags |= O_NONBLOCK;
        int ret = fcntl(STDIN_FILENO, F_SETFL, flags);
        if(ret == -1){
            perror("fcntl error");
            exit(1);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    58P 系统调用lseek

    • lseek函数通常用于随机访问文件,例如读取文件中的某个特定位置的数据。
    • 函数声明:
    #include 
    
    off_t lseek(int fd, off_t offset, int whence);
    
    
    • 1
    • 2
    • 3
    • 4

    fd是文件描述符,offset是偏移量,whence是偏移量的起始位置。whence可以取以下三个值之一:

    - `SEEK_SET`:偏移量相对于文件开头。
    - `SEEK_CUR`:偏移量相对于当前位置。
    - `SEEK_END`:偏移量相对于文件末尾。
    
    • 1
    • 2
    • 3

    返回值是新的文件偏移量(-1表示错误)

    • 常用作用:使用lseek 获取文件大小、配合truncate拓展文件大小
    • 使用lseek获取文件大小的例子:
    #include 
    #include 
    #include 
    #include 
    
    int main(int argc, char *argv[]) {
        if (argc != 2) {
            fprintf(stderr, "Usage: %s \n", argv[0]);
            exit(1);
        }
    
        int fd = open(argv[1], O_RDONLY);
        if (fd == -1) {
            perror("open error");
            exit(1);
        }
    
        off_t size = lseek(fd, 0, SEEK_END);
        if (size == -1) {
            perror("lseek error");
            exit(1);
        }
    
        printf("File size: %ld bytes\n", size);
    
        close(fd);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    59P 传入传出参数

    传入参数: 1. 指针作为函数参数。 2. 同常有 const 关键字修饰。 3. 指针指向有效区域, 在函数内部做读操作。

    传出参数: 1. 指针作为函数参数。 2. 在函数调用之前,指针指向的空间可以无意义,但必须有效。 3. 在函数内部,做写操作。 4。函数调用结束后,充当函数返回值。

    传入传出参数: 1. 指针作为函数参数。 2. 在函数调用之前,指针指向的空间有实际意义。 3. 在函数内部,先做读操作,后做写操作。 4. 函数调用结束后,充当函数返回值。

    60P 目录和inode

    • inode:它是文件系统中的一个数据结构,用于存储文件的元数据信息。每个文件在文件系统中都有一个唯一的inode号码,通过这个号码可以访问文件的元数据信息,例如文件的权限、所有者、大小、创建时间、修改时间等等。
    • 在Linux文件系统中,文件名和inode号码是分开存储的。文件名存储在目录中,而inode号码存储在文件系统的inode表中。
    • 一个文件主要由两部分组成,dentry(目录项)和 inode。所谓的删除文件,就是删除 inode,但是数据其实还是在硬盘上,以后会覆盖掉。(参考某些数据恢复措施)
  • 相关阅读:
    那些年你啃过的ConcurrentHashMap
    目标检测论文解读复现之九:基于改进YOLOv5的复杂场景下SAR图像船舶检测方法
    【golang】context详解
    【FPGA】FPGA实现UART串口通信回环
    数据交换格式
    【课程】SP Module2 辅音和元音的声学
    Azure AD Domain Service(二)为域服务中的机器配置 Azure File Share 磁盘共享
    随身wifi编译Openwrt的ImmortalWrt分支
    影刀rpa办公实例一,汇总报名表
    java毕业设计选题基于SpringBoot项目源码体育用品购物商城-协同过滤推荐算法
  • 原文地址:https://blog.csdn.net/weixin_43303286/article/details/133691207