0%

Linux系统基本知识

1.根目录结构(FSH标准)

  • /bin:所有用户都可以使用的、基本的命令

  • /boot:启动文件,比如内核等

  • /dev:以文件的形式保存 Linux 所有的设备及接口设备

  • /etc:配置文件

  • /home:家目录

  • /root:root用户的家目录

  • /lib:主要放置系统开机使用的、/bin 和 /sbin 目录下的命令使用的库函数

  • /media:插上U盘等外设会挂在到该目录上

  • /mnt:用来挂载其他文件系统

  • /opt:第三方软件放置的目录

  • /proc:这个目录是一个虚拟文件系统,它放置的数据都是在内存当中,例如进程、外部设备状态、网络状态等

  • /sbin:该目录下放置开机过程中需要的命令,包括开机、修复、还原系统等

  • /sys:用来挂载虛拟的sys文件系统,可以查看系统信息:比如设备信息

  • /tmp:置文件的地方

  • /var:放置常态化变动的文件,例如缓存、登录日志文件、软件运行产生的文件等

  • /usr:Unix Software Resource,存放可分享的与不可变动的数据

    • /bin:绝大部分的用户可使用指令都放在这里(与开机无关),/bin中的命令跟开机有关
    • /include:C/C++的头文件和包含文件
    • /lib:库
    • /local:系统管理员在本机自行下载的软件
    • /usr/src/:源码放置的地方
    • /usr/share/:放置共享文件的地方
    • /usr/sbin/:非系统正常运行需要的系统命令

1.1 Shell的执行

  1. 解析用户输入(以空格分割字符串)
  2. 第一个参数为需要待执行程序的名称(在指定路径或者环境变量包含路径中寻找
  3. 其余参数为传递给该程序的参数
  • 举例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //hello.c
    #include <stdio.h>
    int main(int ac, char*av[])
    {
    if(ac >= 2)
    printf("Hello %s\n", av[1]);
    else
    printf("Hello wrold\n");
    return 0;
    }

    使用如下命令编译并执行,则在当前目录下寻找可执行文件hello:

    1
    2
    $ gcc hello.c -o hello
    $ ./hello Krocz

    如果使用如下命令执行,则会在环境变量保存的所有路径中寻找可执行文件hello:

    1
    $ hello Krocz

    可以选择将文件hello放到PATH保存的某个路径中,例如/usr/bin;也可以为环境变量PATH添加新路径

1.2 为环境变量PATH添加新路径

1.2.1 查看PATH

1
echo $PATH

1.2.2 设置

以在PATH添加/home/book目录为例:

  • 永久设置(对所有用户有效):方法1

    修改/etc/environment,添加/home/book路径

    1
    PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/book"
  • 永久设置(只对当前用户有效):方法2

    修改~/.bashrc,在行尾添加:

    1
    export PATH=$PATH:/home/book
  • 临时设置

    在终端执行如下命令,只对当前终端有效:

    1
    export PATH=$PATH:/home/book

2.文件的目录属性

1
2
-rw-rw-r-- 1 zhaoyan zhaoyan 1497 11月 12 14:08 a.txt
drwxrwxr-x 3 zhaoyan zhaoyan 4096 10月 9 18:39 C
  • 模式(mode):首位表示文件类型
    - -:普通文件
    - d:目录
    - c:字符设备文件
    - b:块设备文件
    - l:链接文件
    - s:套接字文件
    - p:管道文件

  • 链接数(links):指该文件被引用的次数
  • 文件所有者(owner):
  • 组(group):文件所有者所在的组
  • 大小(size):显示文件的大小,单位是字节,目录所占空间是以块(每块512字节)为单位进行分配的,所以目录的大小经常是相等的
  • 最后修改时间(last-modified)
  • 文件名(name)

3.常用命令

  • ctrl + c:清空命令并且换行;还可以用来强制中止进程运行
  • ctrl + z:挂起一个进程
  • ctrl + u:清空当前命令行
  • 转义:
    • 命名含有空格:需要加上\转义,例如:mkdir ac\ wing
    • 正则表达式中.通常表示任意字符,因此如果想让点号作为其本意,也需要\转义
  • ls:蓝色的是文件夹,白色的是普通文件,绿色的是可执行文件

3.1 压缩/解压缩命令

3.1.1 gzip/bzip2

  • gzip/bzip2常用选项:

    • -l(list):列出压缩文件的内容
    • -k(keep):在压缩或解压时,保留输入文件
    • -d(decopress):将压缩文件进行解压缩(仅gzip有该参数)
  • 举例:

    1
    2
    3
    gzip -l a.txt.gz        //查看压缩文件信息
    gzip -k a.txt //压缩该文件
    gzip -kd a.txt.gz //解压缩
  • 注意:

    • gzip/bzip2仅能压缩单个文件,不能压缩目录
    • 一般情况下,小文件使用gzip来压缩,大文件使用bzip2来压缩。bzip2的压缩率更高
    • gzip压缩的后缀是.gz,bzip2的压缩后缀是.bz2

3.1.2 tar

  • tar 常用选项:

    • -c(create):表示创建用来生成文件包 。
    • -x:表示提取,从文件包中提取文件。
    • -t:可以查看压缩的文件。
    • -z:使用 gzip 方式进行处理,它与”c“结合就表示压缩,与”x“结合就表示解压缩。
    • -j:使用 bzip2 方式进行处理,它与”c“结合就表示压缩,与”x“结合就表示解压缩。
    • -v(verbose):详细报告 tar 处理的信息。
    • -f(file):表示文件,后面接着一个文件名。
    • -C <指定目录> 解压到指定目录。
  • 举例:

    1
    2
    3
    tar czvf dira.tar.gz dira            //把目录 dira 压缩、打包为 dira.tar.gz 文件
    tar tvf dira.tar.gz //查看压缩文件
    tar xzvf diar.tar.gz -C /home/book //解压到/home/book

3.2 查找/搜索命令

3.2.1 查找文件-find

  • 举例:

    1
    find /home/book/dira/ -name "dir or file name"  // 在指定目录下按名称查找

3.2.2 搜索文件内容-grep

  • grep常用选项:

    • -r:递归
    • -n:显示目标位置的行号
    • -w:完全匹配所给字符串
  • 举例:

    1
    2
    grep -nw "abc" test1.txt        //在文件test1.txt中查找并完全匹配字符串"abc"
    grep -rn "abc" * | grep "\.h" //在当前文件夹下查找字符串"abc",并通过管道将查找结果传给第2个命令

    *是一个通配符,表示匹配任意长度的任意字符。

3.3 改变文件权限-chmod

  • 权限对应数字:r:4 w:2 x:1

  • 用户组对应字母:user:u group:g others:oa表示all,即所有组

  • 举例:

    1
    2
    3
    4
    chmod 777 .bashrc
    chmod -r u=rwx,go=rx dir
    chmod a-x .bashrc
    chmod a+w .bashrc

3.4 文件传输-scp

3.4.1 基本用法

命令格式:

1
scp source destination

source路径下的文件复制到destination
**注意服务器的地址应该写为:user@ip:XXX

3.4.2 举例

1
scp -r ~/tmp user@ip:/home/acs/
  • 将本地家目录中的tmp文件夹复制到user@ip服务器中的/home/acs/目录下。
1
scp -r user@ip:homework . 
  • user@ip服务器中的~/homework/文件夹复制到本地的当前路径下。

3.5 进程状态-ps

ps(process status)用于显示当前进程的状态。

  • 常用参数:
    • -A:列出所有进程
    • -ef:使用System V风格列出进程信息
    • -u:跟用户名参数,显示该用户的进程信息
    • -T:查看线程

3.5.1 举例

  • 分页显示所有进程
1
ps -ef | more

image-20230905211714592

列出信息每字段的含义:

描述
UID 用户的ID ,但输出的是用户名
PID 进程的ID
PPID 父进程的ID
C 进程占用CPU的百分比
STIME 进程启用到现在的时间
TTY 该进程在哪个终端上运行,若与终端无关,则显示?,若为pts/0等,则表示由网络连接主机进程
TIME 该进程实际使用CPU运行的时间
CMD 命令的名称和参数
  • 显示指定用户的进程,通过grep命令筛选
1
ps -u root | grep nfs

3.6 终止进程命令-kill

kill -n:n表示信号编号

  • kill pidkill -15 pid

    系统会发送一个SIGTERM的信号给对应的程序。当程序接收到该signal后,将会发生以下的事情:

    1. 程序立刻停止
    2. 当程序释放相应资源后再停止
    3. 程序可能仍然继续运行,例如程序正在等待IO,可能就不会立马做出相应

    也就是说,SIGTERM多半是会被阻塞的、忽略。

  • kill -9 pid

    系统会发送一个SIGKILL的信号给对应的程序。用来强制尽快终止一个进程。绝大部分程序收到后都会立刻终止。

3.7 编译命令-make

  • 常见参数

    参数 描述
    -c DIR or --directory=DIR 在读取 Makefile 之前,进入到目录 DIR,然后执行 make。
    -f FILE or --file=FILE 指定文件 “FILE” 为 make 执行的 Makefile 文件

3.8 内核模块命令

1
2
3
4
5
6
insmod hello_drv.ko    //安装内核驱动模块
cat /proc/devices // 查看/proc/devices文件,该文件列出字符和块设备的主设备号,以及分配到这些设备号的设备名称
lsmod // 列出所有已安装的内核模块
ls /dev/hello -l // 查看设备节点是否存在
rmmod hello_drv // 卸载内核驱动模块
dmesg // 查看内核输出的打印信息

3.9 查看进程的内存映射区域

1
cat /proc/<进程PID>/maps

每行的格式如下:

1
address  perms offset  dev   inode   pathname
  • address(地址范围): 表示映射的虚拟地址范围。这是一个区间,以十六进制表示,包括起始地址和结束地址。例如,08048000-08056000 表示一个从 0x080480000x08056000 的地址范围。
  • perms(权限标志): 表示对该内存区域的访问权限。常见的权限标志包括:
    • r:可读(read)
    • w:可写(write)
    • x:可执行(execute)
    • p:私有(private) - 表示该区域是进程私有的,对其他进程不可见。
    • s:共享 (share)
  • offset(文件偏移量): 对于映射的文件来说,表示在文件中的偏移量。对于非文件映射,这通常是0。
  • dev(设备标识): 表示映射的文件所在的设备。它由两个十六进制数表示,分别表示主设备号和次设备号。
  • inode(节点号): 表示映射的文件在文件系统中的索引节点号。
  • pathname(文件路径): 表示映射的文件的路径。如果是匿名映射(例如堆、栈等),可能显示为[stack][heap]等。

4. 记录环境搭建过程

  1. 在Ubuntu上安装基本开发环境

  2. 通过repo命令下载BSP:

    1. 板级支持包-Board Support Package:构建嵌入式操作系统所需的引导程序(Bootloader)、内核(Kernel)、根文件系统(Rootfs)和工具链(Toolchain) 提供完整的软件资源包。

    2. ~/100ask_imx6ull_mini-sdk$ ../repo/repo init -u https://gitee.com/weidongshan/manifests.git -b linux-sdk -m imx6ull/100ask_imx6ull_mini_linux4.9.88_release.xml --no-repo-verify
      
      ~/100ask_imx6ull_mini-sdk$ ../repo/repo sync -j4
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24

      3. `../repo/repo init`: 这是命令本身,指示系统执行repo工具进行初始化操作。

      4. `-u https://gitee.com/weidongshan/manifests.git`: `-u`选项指定了远程仓库的URL。在这个命令中,远程仓库的URL是`https://gitee.com/weidongshan/manifests.git`,即来自Gitee平台的`manifests.git`仓库。

      5. `-b linux-sdk`: `-b`选项指定了要下载的分支。在这个命令中,分支是`linux-sdk`。

      6. `-m imx6ull/100ask_imx6ull_mini_linux4.9.88_release.xml`: `-m`选项指定了清单文件的路径。在这个命令中,清单文件的路径是`imx6ull/100ask_imx6ull_mini_linux4.9.88_release.xml`。

      7. `--no-repo-verify`: 这是一个额外的选项,用于跳过对repo的验证。如果仓库包含了repo和.git/ repo目录已经被修改或破坏,这个选项可以防止运行`repo init`时出现错误。

      8. `./repo/repo sync`: 这是命令本身,指示系统执行repo工具进行代码仓库的同步操作。

      9. `-j4`: `-j`选项用于指定并行任务的数量,后面的数字4表示同时执行4个任务。这个选项可以根据系统性能和网络环境进行调整,以加快代码同步的速度。

      3. 配置交叉编译工具链(仅对当前用户有效):

      1. ```shell
      1.在 ~/.bashrc中添加:
      export ARCH=arm
      export CROSS_COMPILE=arm-buildroot-linux-gnueabihf-
      export PATH=$PATH:/home/book/100ask_imx6ull_mini-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin

      2.设置完成之后执行 source ~/.bashrc
    3. 执行了source ~/.bashrc命令,它会重新加载你对~/.bashrc文件的修改,使得刚才添加的环境变量生效。

  3. 在Windows使用VSCode搭建嵌入式Linux开发环境_韦东山的博客-CSDN博客

    1. 安装bear:sudo apt-get install bear.

      • Bear是一种生成代码注释的工具。它可以扫描源代码文件,并根据函数、类、变量等的定义自动生成注释模板。通过使用Bear,开发人员可以快速地为自己的代码添加注释,提高代码的可读性和可维护性。注释可以在代码中提供有关功能、参数、返回值等的说明,帮助开发人员理解代码的作用和使用方法。
      • Bear的用法:bear make [其他make命令的参数],bear会记录make编译文件过程中被调用的编译器命令,以便生成编译数据库。编译数据库(compile_commands.json文件)在后续的代码分析和语义补全等开发工具中可以使用。
    2. 编译内核:

      1
      2
      3
      $ cd /home/book/100ask_imx6ull-sdk/Linux-4.9.88
      $ make 100ask_imx6ull_defconfig
      $ bear make zImage -j4
      • 100ask_imx6ull_defconfig是Linux内核提供的一个配置文件,用于设置编译选项和配置信息,从而能够编译出与开发板相对应的配置
      • 使用 make 工具执行 zImage 目标,该目标用于编译 Linux 内核。

5. Linux系统的环境变量

在配置和使用交叉编译器时,我使用了如下命令:

1
2
3
4
5
6
配置:
export ARCH=arm
export CROSS_COMPILE=arm-buildroot-linux-gnueabihf-
export PATH=$PATH:/home/book/100ask_imx6ull_mini-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin
使用:
arm-buildroot-linux-gnueabihf-gcc -o hello hello.c

5.1 配置命令解读

ARCH,CROSS_COMPILE,PATH是Linux系统中被广泛使用的特定环境变量。

  1. ARCH=arm:指定编译的目标架构为ARM,这是为了告诉系统你将使用ARM架构的交叉编译工具链。
  2. CROSS_COMPILE=arm-buildroot-linux-gnueabihf-:这个变量指定了交叉编译工具链的前缀。CROSS_COMPILE是一个特定环境变量,用以命令补全。
  3. arm-buildroot-linux-gnueabihf-gcc -o hello hello.c使用该工具链中的gcc编译器进行编译,如果想编译Java文件,则应使用arm-buildroot-linux-gnueabihf-javac
  4. PATH=$PATH:/home/book/100ask_imx6ull_mini-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin:将交叉编译工具链的路径添加到系统的PATH环境变量中,从而可以寻找到命令的可执行文件。

5.2 交叉编译工具链

  • 交叉编译器前缀之所以设置为arm-buildroot-linux-gnueabihf,这是由于工具链的命名约定。不同的交叉编译器前缀对应不同的架构和操作系统。

  • 例如,”arm-buildroot-linux-gnueabihf-“前缀表示编译器适用于ARM架构,并且在Linux环境下使用GNUEABI的标准。eabi表示嵌入式应用二进制接口,hf表示硬浮点支持,buildroot表示交叉编译器是基于Buildroot嵌入式Linux构建系统生成的。

  • 常见的交叉编译器前缀示例:

    • arm-linux-gnueabi-:用于ARM架构的Linux环境下的GNUEABI标准。
    • arm-linux-gnueabihf-:用于ARM架构的Linux环境下的GNUEABIHF标准,支持硬浮点运算。
    • arm-none-linux-gnueabi-:用于ARM架构的无操作系统或裸机环境下的GNUEABI标准。
    • arm-none-eabi-:用于ARM架构的无操作系统或裸机环境下的EABI(嵌入式应用程序接口)标准。
    • mips-linux-gnu-:用于MIPS架构的Linux环境下的GNU标准。
    • powerpc-linux-gnu-:用于PowerPC架构的Linux环境下的GNU标准。
    • x86_64-linux-gnu-:用于x86_64架构的Linux环境下的GNU标准。

5.3 Linux中常用环境变量

  1. PATH:这是一个包含可执行文件路径的环境变量。当你输入一个命令时,Shell会在PATH中定义的路径中搜索可执行文件。
  2. HOME:表示当前用户的主文件夹路径。当你打开终端或使用文件系统路径时,它可以帮助系统定位到当前用户的主文件夹。
  3. USER:表示当前登录用户的用户名。
  4. TERM:此变量定义了终端类型。它告诉系统如何正确处理和显示终端上的输出,以确保兼容性和正确的显示。
  5. PS1:这是Shell提示符的设置。它定义了你在命令行中看到的用户提示符的样式和内容。
  6. LANGLC_ALL:这些环境变量用于指定系统的语言和地区设置。它们对于国际化和本地化非常重要,帮助系统在正确的语言环境下运行和显示信息。
  7. SHELL:表示当前使用的Shell。当你同时安装了多个Shell时,这个变量可以帮助系统确定正在使用的默认Shell。
  • 环境变量配置文件的位置:
    • ~/.bash_profile:用于个人用户的bash登录 shell的配置文件。
    • ~/.bashrc:用于个人用户的bash非登录 shell的配置文件。
    • /etc/profile:用于全局系统范围的bash登录 shell的配置文件。
    • /etc/environment:用于整个系统的全局环境变量配置文件。

6. 动态链接器

动态链接器是一个独立于应用程序的进程, 属于操作系统, 当用户的程序需要加载动态库的时候动态连接器就开始工作了,很显然动态连接器根本就不知道用户通过 gcc 编译程序的时候通过参数 -L 指定的路径。

那么动态链接器是如何搜索某一个动态库的呢,在它内部有一个默认的搜索顺序,按照优先级从高到低的顺序分别是:

  1. 可执行文件内部的 DT_RPATH 段

  2. 系统的环境变量 LD_LIBRARY_PATH

  3. 系统动态库的缓存文件 /etc/ld.so.cache

  4. 存储动态库/静态库的系统目录 /lib/, /usr/lib等

按照以上四个顺序, 依次搜索, 找到之后结束遍历, 最终还是没找到, 动态连接器就会提示动态库找不到的错误信息。

6.1 配置动态库路径

可执行程序生成之后, 根据动态链接器的搜索路径, 我们可以提供三种解决方案,我们只需要将动态库的路径放到对应的环境变量或者系统配置文件中,同样也可以将动态库拷贝到系统库目录(或者是将动态库的软链接文件放到这些系统库目录中)。

方案1: 将库路径添加到环境变量 LD_LIBRARY_PATH 中

  1. 找到相关的配置文件
  • 用户级别: ~/.bashrc —> 设置对当前用户有效
  • 系统级别: /etc/profile —> 设置对所有用户有效
  1. 使用 vim 打开配置文件, 在文件最后添加这样一句话

    1
    2
    # 自己把路径写进去就行了
    export LD_LIBRARY_PATH =$LD_LIBRARY_PATH:动态库的绝对路径
  2. 让修改的配置文件生效

    • 修改了用户级别的配置文件, 关闭当前终端, 打开一个新的终端配置就生效了

    • 修改了系统级别的配置文件, 注销或关闭系统, 再开机配置就生效了

    • 不想执行上边的操作, 可以执行一个命令让配置重新被加载

      1
      2
      3
      4
      # 修改的是哪一个就执行对应的那个命令
      # source 可以简写为一个 . , 作用是让文件内容被重新加载
      $ source ~/.bashrc (. ~/.bashrc)
      $ source /etc/profile (. /etc/profile)

方案2: 更新 /etc/ld.so.cache 文件

  1. 找到动态库所在的绝对路径(不包括库的名字)比如:/home/robin/Library/

  2. 使用vim 修改 /etc/ld.so.conf 这个文件, 将上边的路径添加到文件中(独自占一行)

    1
    2
    3
    4
    # 1. 打开文件
    $ sudo vim /etc/ld.so.conf

    # 2. 添加动态库路径, 并保存退出
  3. 更新 /etc/ld.so.conf 中的数据到 /etc/ld.so.cache

    1
    2
    # 必须使用管理员权限执行这个命令
    $ sudo ldconfig

方案3: 拷贝动态库文件到系统库目录 /lib/ 或者 /usr/lib 中 (或者将库的软链接文件放进去)

1
2
3
4
5
# 库拷贝
sudo cp /xxx/xxx/libxxx.so /usr/lib

# 创建软连接
sudo ln -s /xxx/xxx/libxxx.so /usr/lib/libxxx.so

验证是否能加载到对应动态库

在启动可执行程序之前, 或者在设置了动态库路径之后, 我们可以通过一个命令检测程序能不能够通过动态链接器加载到对应的动态库, 这个命令叫做 ldd

1
2
3
4
5
6
7
8
9
# 语法:
$ ldd 可执行程序名

# 举例:
$ ldd app
linux-vdso.so.1 => (0x00007ffe8fbd6000)
libcalc.so => /home/robin/Linux/3Day/calc/test/libcalc.so (0x00007f5d85dd4000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5d85a0a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5d85fd6000) ==> 动态链接器, 操作系统提供