Linux 基础知识Ⅰ

- 18 分钟前

配套食用:哔哩哔哩黑马 Linux 基础教程 P1 - P98;


快捷键

目录

[joki@localhost ~]$

文件操作

命令

[joki@localhost ~]$ ls ~
cpp  install.sh
[joki@localhost ~]$ ls -a
.   .bash_history  .bash_profile  .cache   cpp      install.sh  .local    .pki  .VimForCpp  .ycm_extra_conf.py
..  .bash_logout   .bashrc        .config  .cquery  .LfCache    .mozilla  .vim  .vimrc
[joki@localhost ~]$ ls -l
total 4
drwxrwxr-x. 3 joki joki  17 Apr  2 13:06 cpp
-rw-rw-r--. 1 joki joki 827 Apr  2 11:50 install.sh
mkdir aa/bb/cc -p
mkdir -p bb/cc/dd
rm -r aa #递归删除目录下的所有内容
rm -ri aa #询问是否确认进入、删除目录
touch fileA # 创建文件, 若已有filaA,修改文件时间
cp source dest #若已有同名目标文件,会直接覆盖

查看文件内容:cat是一次性显示整个文件的内容,还可以将多个文件连接起来显示,它常与重定向符号配合使用,适用于文件内容少的情况; more和less一般用于显示文件内容超过一屏的内容,并且提供翻页的功能。more比cat强大,提供分页显示的功能,less比more更强大,提供翻页,跳转,查找等命令。而且more和less都支持:用空格显示下一页,按键b显示上一页。

cat filename #显示文件所有内容
more filename # 先显示一屏幕,然后回车一行一行显示文件内容,空格下一屏,b上一页,q退出
less filename
head -n 5 filename #显示文件的前 n 行
tail -n 5 filename #显示文件的后 n 行

软连接与硬连接

文件权限

文件查找

磁盘

磁盘设备种类

命名规则:sda sdb sdc sdd 最多可以允许有4个硬盘,每个硬盘有分区,最多有4个主分区1,2,3,4,扩展分区标号从 5 开始。

[joki@localhost ~]$ sudo fdisk -l
[sudo] joki 的密码:

磁盘 /dev/sda:240.1 GB, 240057409536 字节,468862128 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 4096 字节
I/O 大小(最小/最佳):4096 字节 / 4096 字节
磁盘标签类型:dos
磁盘标识符:0x00071654

   设备 Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     2099199     1048576   83  Linux
/dev/sda2         2099200   468860927   233380864   8e  Linux LVM

压缩包管理

原始压缩工具

[joki@localhost day2]$ ls
animal  backup  cat.txt  dog.txt  fish.txt  test
[joki@localhost day2]$ gzip *.txt # 使用 gzip 压缩后缀为.txt的文件
[joki@localhost day2]$ ls
animal  backup  cat.txt.gz  dog.txt.gz  fish.txt.gz  test
[joki@localhost day2]$ gunzip *.gz # 解压缩gzip 压缩的文件
[joki@localhost day2]$ ls
animal  backup  cat.txt  dog.txt  fish.txt  test

进化

进程管理

[inger@VM-0-4-centos ~]$ who # 查看当前在线用户的情况
inger    pts/0        2021-04-14 15:51 (113.140.6.195)

登陆的用户名, 使用的设备终端,登陆到系统的时间

tty7 桌面终端?tty 1-6 文字终端

pts/0: 设备终端

[inger@VM-0-4-centos ~]$ ps a # 
  PID TTY      STAT   TIME COMMAND
 1283 tty1     Ss+    0:00 /sbin/agetty --noclear tty1 linux
 1284 ttyS0    Ss+    0:00 /sbin/agetty --keep-baud 115200,38400,9600 ttyS0 vt220
19450 pts/0    Ss     0:00 -bash
20563 pts/1    Ss+    0:00 -bash
20630 pts/0    R+     0:00 ps a
[inger@VM-0-4-centos ~]$ ps au # 列出更加丰富的信息
[inger@VM-0-4-centos ~]$ ps aux # 再加上没有终端的进程信息
ps aux 参数会给出一堆信息,可以通过管道( )进行重定向。*command1 command 2* 将 command 1 的输出作为command 2 的输入,不显示在屏幕上。
[inger@VM-0-4-centos ~]$ ps aux | grep bash
inger    19450  0.0  0.1 116728  3164 pts/0    Ss   15:51   0:00 -bash
inger    20563  0.0  0.1 116728  3156 pts/1    Ss+  15:58   0:00 -bash
inger    21840  0.0  0.0 112816   988 pts/0    R+   16:06   0:00 grep --color=auto bash # 最后一条并不是我们查找到的内容,而是grep在查找 bash 时占用的进程。
[inger@VM-0-4-centos ~]$ kill -l # 查看信号 使用 kill -9 PID 可以杀死一个进程
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX
[inger@VM-0-4-centos ~]$ kill -9 19450 
Connection to 121.4.61.226 closed. 

查看当前进程的环境变量:

[inger@VM-0-4-centos ~]$ env | grep PATH
LD_LIBRARY_PATH=:/home/inger/.VimForCpp/vim/bundle/YCM.so/el7.x86_64
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/inger/.local/bin:/home/inger/bin

Linux 下环境变量的格式是一个 key-value 格式的键值对,格式为 PATH = value1 : value2 : value3 : value4 : ...

Linux 下 top 指令打开类似于 windows 下的任务管理器,但是只能查看,不能做任何操作。

网络管理

[inger@VM-0-4-centos ~]$ ifconfig # 查看本机网络信息
[inger@VM-0-4-centos ~]$ ping baidu.com
PING baidu.com (220.181.38.148) 56(84) bytes of data.
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=1 ttl=49 time=26.8 ms
[inger@VM-0-4-centos ~]$ nslookup baidu.com
Server:		183.60.83.19
Address:	183.60.83.19#53

Non-authoritative answer: # 百度的服务器地址
Name:	baidu.com
Address: 220.181.38.148
Name:	baidu.com
Address: 39.156.69.79

nslookup 获取域名所对应的 ip, 为什么服务器可以知道域名的服务器地址?之前连过会有本地缓存,系统有一些默认的域名对应的 ip 地址,每次连网的时候都会刷新。

服务器搭建

ftp – vsftpd:文件的上传和下载

服务器端允许用户登陆,并给予一些访问权限,所以服务器端需要 修改配置文件,然后 重启服务

  1. 安装 sudo yum install vsftpd
  2. 修改 /etc/vsftpd/vsftpd.conf 配置文件
  3. 重启服务 sudo service vsftpd restart

客户端:

ssh username@ip

scp: super copy, 使用该命令的前提就是主机成功安装 openssh-server,可以实现不同主机之间的文件复制。

scp -r 目标用户名@目标主机ip:/目标文件的绝对路径 保存到本机的绝对(相对)路径

用户管理

创建用户: sudo adduser username,adduser 本质上是一个脚本,所以用起来比较方便。用户名不可以有大写字母。

修改当前用户密码:passwd

创建用户组: sudo groupadd groupname

删除用户:sudo deluser username , sudo userdel -r username 连同家目录一起删掉

[inger@VM-0-4-centos ~]$ vi /etc/passwd # 查看当前系统的所有用户

VIM

垂直分屏:/:vsp filename

切换操作:ctrl + ww

退出所有: :qall

系统级配置文件目录:/etc/vim/vimrc

用户及配置文件目录:~/.vim/vimrc

GCC

参数:

静态库

命名规则: lib + name + .a

制作步骤:1. 生成对应的.o 文件(与位置相关的),2. 使用 ar 静态库打包工具将生成的.o文件打包 ar rcs + 静态库(libname.a) + 生成的所有 .o

[inger@VM-0-4-centos src]$ tree ../../
../../
└── include
    ├── head.h
    └── src
        ├── add.c
        └── mul.c

2 directories, 3 files
[inger@VM-0-4-centos src]$ gcc *.c -c -I ../../include/
[inger@VM-0-4-centos src]$ ls
add.c  add.o  mul.c  mul.o
[inger@VM-0-4-centos src]$ ar rcs libCalc.a *.o # 将后缀为 .o 的目标文件打包成静态库
[inger@VM-0-4-centos src]$ ls
add.c  add.o  libCalc.a  mul.c  mul.o
[inger@VM-0-4-centos day3]$ gcc main.c lib/libCalc.a -o main -Iinclude # 调用静态库
[inger@VM-0-4-centos day3]$ ./main
48
# 调用静态库的第二种方式
gcc main.c -Iinclude -L lib -l Calc -o myapp #-L 库目录 -l:库名

[inger@VM-0-4-centos lib]$ nm libCalc.a # 查看静态库中的内容

add.o:
0000000000000000 T add  # T 表示代码区

mul.o:
0000000000000000 T mul

若main函数中引用静态库中的某个函数,则会在编译时将用到的 .o 文件一起打包到可执行文件中。也就是说,静态库打包的最小单位是 .o 文件

静态库的优点

  1. 发布程序的时候,不需要提供对应的库;
  2. 由于库已经被打包到了可执行文件中,所以库的加载速度会很快

静态库的缺点

  1. 库很多的情况下,导致库的体积很大,从而可执行文件也会变大;
  2. 库发生改变时,需要重新编译程序;当程序很大的时候,有可能编译一次,一天就过去了。

动态库(共享库)

Linux 动态库对应 windows 中的 DLL 文件。

命名规则: lib + name + .so

制作步骤:1. 生成与位置无关的代码 (.o文件);2. 使用 gcc 将 .o 打包成动态库。

[inger@VM-0-4-centos src]$ ls
add.c  mul.c
[inger@VM-0-4-centos src]$ gcc -fPIC -c *.c -I../include # 生成与位置无关的代码
[inger@VM-0-4-centos src]$ ls
add.c  add.o  mul.c  mul.o
[inger@VM-0-4-centos src]$ gcc -shared -o libCalc.so *.o -Iinclude # 打包动态库
[inger@VM-0-4-centos src]$ ls
add.c  add.o  libCalc.so  mul.c  mul.o
[inger@VM-0-4-centos day3]$ gcc main.c lib/libCalc.so -o maind -Iinclude # 使用动态库
[inger@VM-0-4-centos day3]$ ./maind
48
[inger@VM-0-4-centos day3]$ gcc main.c -Iinclude -L./lib -lCalc -o maind2 # 第二种使用动态库的方式,链接错误
[inger@VM-0-4-centos day3]$ ./maind2
./maind2: error while loading shared libraries: libCalc.so: cannot open shared object file: No such file or directory
#ldd 查看可执行程序运行时用到的所有动态库
[inger@VM-0-4-centos day3]$ ldd maind2
	linux-vdso.so.1 =>  (0x00007ffd38dd4000)
	libCalc.so => not found
	libc.so.6 => /lib64/libc.so.6 (0x00007fa843620000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fa8439ee000) # 通过这个ld链接器链接的
[inger@VM-0-4-centos day3]$ echo $LD_LIBRARY_PATH
:/home/inger/.VimForCpp/vim/bundle/YCM.so/el7.x86_64
[inger@VM-0-4-centos day3]$ vim ~/.bashrc # 修改 LD_LIBRARY_PATH 环境变量
[inger@VM-0-4-centos day3]$ source ~/.bashrc
[inger@VM-0-4-centos day3]$ ldd maind2
	linux-vdso.so.1 =>  (0x00007fff5b1fb000)
	libCalc.so => /home/inger/linux/day3/lib/libCalc.so (0x00007f2e8d9e6000) # 此时就找到了动态库目录
	libc.so.6 => /lib64/libc.so.6 (0x00007f2e8d618000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f2e8dbe8000)
[inger@VM-0-4-centos day3]$ echo $LD_LIBRARY_PATH
:/home/inger/.VimForCpp/vim/bundle/YCM.so/el7.x86_64:/home/inger/.VimForCpp/vim/bundle/YCM.so/el7.x86_64:/home/inger/linux/day3/lib

动态库链接错误解决方案

动态库通过动态链接器被调用,动态连接器的本质就是一个动态库。动态链接器的调用规则是根据环境变量调用的,/lib中存放所有文件执行时用到的动态库,所以该问题的解决方式 1 是将 .so 文件放到 /lib 目录中,但这种方式在实际情况中不能这样做,因为有可能用户创建的动态库与系统动态库产生重名问题,从而造成严重错误。

第二种解决方式是配置 LD_LIBRARY_PATH 环境变量(不常用),将动态库路径指定给该环境变量后,在调用时会先于系统动态库查找相应路径。

第三种临时测试时使用 LIB_LIBRARY_PATH = 动态库路径,然后 exprot LD_LIBRARY_PATH ,或者 export LD_LIBRARY_PATH=./lib, 终端关闭时失效。

第四种解决方式(推荐):找到动态链接器的配置文件,将动态库的路径写到配置文件/etc/ld.so.conf中并更新sudo ldconfig -v

动态库的优点

  1. 执行程序体积小;
  2. 动态库函数接口不变的情况下更新不需要重新编译程序;

动态库的缺点

  1. 发布程序的时候,需要将动态库提供给用户;
  2. 动态库没有打包到应用程序中,所以在加载速度会稍微慢一点。

GDB

[inger@VM-0-4-centos mysort]$ gdb app # 1. 启动 gdb
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/inger/linux/day3/mysort/app...done.
(gdb) l # l 查看程序源码, 每次只会列出来 10 行,按回车默认执行上一次命令可以继续看
1	#include <stdio.h>
2	#include "sort.h"
3
4	int main(){
5	  int i;
6	  int arr1[] = {9, 10 , 3, 4, 6, 29, 8, 17, 55, 80, 98, 50, 20, 115, 79, 34};
7	  int arr2[] = {9, 10 , 3, 4, 6, 29, 8, 17, 55, 80, 98, 50, 20, 115, 79, 34};
8
9	  int len = sizeof(arr1) / sizeof(arr1[0]);
10
(gdb) l main.c:main
1	#include <stdio.h>
2	#include "sort.h"
3
4	int main(){
5	  int i;
6	  int arr1[] = {9, 10 , 3, 4, 6, 29, 8, 17, 55, 80, 98, 50, 20, 115, 79, 34};
7	  int arr2[] = {9, 10 , 3, 4, 6, 29, 8, 17, 55, 80, 98, 50, 20, 115, 79, 34};
8
9	  int len = sizeof(arr1) / sizeof(arr1[0]);
10
(gdb)
11	  printf("Sort Array: \n");
12	  for(i = 0; i < len; ++i){
13	    printf("%d\t", arr1[i]);
14	  }
15	  printf("\n");
16
17	  selectionSort(arr1, len);
18	  printf("Selection Sort: \n");
19	  for(i = 0; i < len; ++i){
20	    printf("%d  ", arr1[i]);
(gdb) break 17 # 在17行打断点
Breakpoint 1 at 0x4007c1: file main.c, line 17.
(gdb) break 13 if i == 10 # 循环当 i == 10 的时候打一个断点
Breakpoint 2 at 0x400791: file main.c, line 13.
(gdb) i b # 查看断点信息
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004007c1 in main at main.c:17
2       breakpoint     keep y   0x0000000000400791 in main at main.c:13
	stop only if i == 10
(gdb) info break
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004007c1 in main at main.c:17
2       breakpoint     keep y   0x0000000000400791 in main at main.c:13
	stop only if i == 10

Makefile

当项目很大的时候,gcc 编译指令会非常复杂,所以我们使用代码管理工具 makefile,将所有的代码编译命令都写到 makefile 中,就不需要我们手动再去敲很复杂的 gcc 了。

Makefile 文件中记录了编译程序的一些步骤。公司中的 makefile 都是架构师或者大牛写的,我们只需要编写指定模块就好了。

如果是我们自己的项目,写一个比较菜的 makefile 指令就够用了。

makefile 有两种命名规则 首字母大写或全部小写的 makefile.

[inger@VM-0-4-centos makefile]$ ls
add.c  head.h  main.c  mul.c
[inger@VM-0-4-centos makefile]$ touch makefile
[inger@VM-0-4-centos makefile]$ vim makefile
[inger@VM-0-4-centos makefile]$ cat makefile # 查看 makefile 中的内容
app:main.c add.c mul.c # 目标【最终要生成的文件名字】: 依赖【生成目标所需要的原材料】
		gcc main.c add.c mul.c -o app # tab【必须有!】 命令
[inger@VM-0-4-centos makefile]$ make # 使用 make 指令生成 app
gcc main.c add.c mul.c -o app
[inger@VM-0-4-centos makefile]$ ls
add.c  app  head.h  main.c  makefile  mul.c

makefile 规则:目标,依赖,命令。

app:main.c add.c mul.c 
		gcc main.c add.c mul.c -o app 

第一个版本的 makefile 存在缺陷,文件很多的情况下,编译效率是非常低的。我们想要达到的效果是,修改一次就编译一次,不修改就不编译的。那么就需要生成 .o。第二个版本的makefile如下:

app:main.o add.o mul.o
  gcc main.o add.o mul.o -o app
main.o:main.c
  gcc -c main.c
add.o:add.c
  gcc -c add.c
mul.o:mul.c
  gcc -c mul.c

第一条规则用来生成最终目标app,后面三条规则用于生成子目标,这些子目标是用来生成最终目标的依赖。当调用第一个规则时会发现不存在依赖,所以会往下查找有没有生成依赖的规则,找到了就会先执行下面的规则。在v2版本的 makefile 中,第一条规则是最后被执行的。使用 v2 版本的 makefile,当文件修改时,无需调用其他文件的编译命令。第一条规则中的命令,不管什么时候都会被最后执行。

makefile 向下检索,构建出一棵关系依赖树,从下向上执行命令,生成最终目标文件。目标是通过依赖生成的,makefile 通过比较目标和依赖的时间,当依赖的时间大于之前的目标时间时,就会调用编译命令来进行更新;如果依赖的时间比之前的目标时间短,就不需要调用编译命令了。

makefile 可以用自定义变量、模式规则中的公式等进行替换:

obj=main.o add.o mul.o
target=app
$(target):$(obj)
  gcc $(obj) -o $(target)
%.o:%.c
  gcc -c $< -o $@

:warning: 注: 以上三个符号的规则只能在命令中使用。

makefile 中也有一些自己维护的变量,系统维护的变量有些是有默认值,有些没有,可以由用户设置。

用户可以修改变量的默认值,比如 CC=gcc

obj=main.o add.o mul.o
target=app
# makefile 中自己维护的变量
CC=gcc
CPPFLAGS = -I
$(target):$(obj)
	 $(CC) $(obj) -o $(target)
%.o:%.c
	$(CC) -c $< -o $@

这样makefile看起来就更高大上了。

Makefile 中的函数

v4 版本的 makefile 对带有变量的 v3 版 makefile 进行改进,makefile 有自带的函数可以完成一些工作,且 makefile 中的所有函数都是有返回值的,如:

#obj=main.o add.o mul.o
target=app
# makefile 中自己维护的变量
src=$(wildcard ./*.c) # 查找当前目录下的所有 .c 文件
obj=$(patsubst ./%.c, ./%.o, $(src))
CC=gcc
CPPFLAGS = -I
# 直接 make 时生成顶级目标
$(target):$(obj)
	 $(CC) $(obj) -o $(target)
%.o:%.c
	$(CC) -c $< -o $@

# make clean: 直接执行下面的命令,不生成顶级目标
clean:
	# 命令前加 - 表示该命令执行失败时忽略该命令;
	-rm $(obj) $(target)
# make hello: 直接执行下面命令,不生成顶级目标
hello:
	echo "hello makefile!\n"

更多内容可以详细查看 GNU make 官方文档。

虚拟地址空间

为了防止不同进程同一时刻在物理内存中运行而对物理内存的争夺和践踏,采用了虚拟内存1

Linux 每一个运行的程序操作系统都会为其分配 0 - 4G 的虚拟地址空间。 虚拟内存技术使得不同进程在运行过程中,它所看到的是自己独自占有了当前系统的4G内存。所有进程共享同一物理内存,每个进程只把自己目前需要的虚拟内存空间映射并存储到物理内存上。

事实上,在每个进程创建加载时,内核只是为进程“创建”了虚拟内存的布局,具体就是初始化进程控制表中内存相关的链表,实际上并不立即就把虚拟内存对应位置的程序数据和代码(比如.text .data段)拷贝到物理内存中,只是建立好虚拟内存和磁盘文件之间的映射就好(叫做存储器映射),等到运行到对应的程序时,才会通过 缺页异常 来拷贝数据。还有进程运行过程中,要动态分配内存,比如malloc时,也只是分配了虚拟内存,即为这块虚拟内存对应的页表项做相应设置,当进程真正访问到此数据时,才引发缺页异常。

请求分页系统、请求分段系统和请求段页式系统都是针对虚拟内存的,通过请求实现内存与外存的信息置换。

虚拟地址空间中 1G 内核空间中的PCB 进程控制块,PCB中会维持一张文件描述符表,每打开一个新文件会占用一个文件描述符,而且使用的是空闲的最小的一个文件描述符。

用户地址空间(从 0 地址到 3G,从下往上)分别是:

从 .text 到 .bss 段合起来称之为 ELF(Linux 下可执行文件格式);

程序执行时,从代码段开始执行,然后开始初始化全局变量。程序执行过程中,每当遇到1个局部变量,就在栈空间中从上往下开始分配空间,也就是从高地址向低地址空间开始分配;每当遇到 new 或 malloc 的变量, 从堆空间中分配内存;每当调用动态库时,将其加载到共享区中的空闲位置,所以,动态库的生成的时候必须生成与位置无关的代码,也是因为库程序的执行必须相对位置;静态库打包后,程序代码段是在代码段的,所以每次在内存中存放的位置都是固定的。

CPU 为什么要使用虚拟地址空间与物理地址空间映射?解决了什么问题

  1. 方便编译器和操作系统安排程序的地址分布。程序可以使用一系列相邻的虚拟地址来访问物理内存中不相邻的大内存缓冲区;
  2. 方便进程之间隔离。不同进程使用的虚拟地址彼此隔离,一个进程中的代码无法更改正在由另一进程使用的物理内存;
  3. 方便操作系统使用较小的内存空间 。程序可以使用一系列虚拟地址来访问大于可用物理内存的内存缓冲区。当物理内存的供应量变小时,内存管理器会将物理内存页(通常大小为 4KB )保存到磁盘文件。数据或代码页会根据需要在物理内存与磁盘之间移动。

文件系统函数

当 C 文件中调用 printf 标准输出函数时,发生了什么?

调用 printf("hello"); 的文件指针包含一个 C 库函数维护的缓冲区,调用 linux 系统的 write(fd, "hello", 5) 函数将文件描述符传递到系统 API 的应用层调用,write 函数做一个从用户空间到内核空间的系统调用sys_write(), 系统调用调用设备驱动,通过内核层的设备驱动函数操作硬件,将其显示在显示器中。

从 p78 开始介绍文件操作函数,这块目前应该用不到,先不看了,进入下一个课程的学习。


Inger Notes © 2023
rss facebook twitter github gitlab youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora qq quora wechat