Linux 学习笔记

Linux是一种免费、开放源代码的操作系统,它由林纳斯·托瓦兹(Linus Torvalds)在 1991 年开发。

Linux 基于 Unix 操作系统,但是它是一个独立的操作系统,不是 Unix 的衍生版。

Linux 基础知识

Linux 有哪些发行版

  • Ubuntu:一个基于Debian的发行版,适用于桌面和服务器。
  • Debian:一个稳定且流行的发行版,用于桌面和服务器。
  • CentOS:一个基于Red Hat Enterprise Linux的发行版,用于服务器。
  • Fedora:一个基于Red Hat的发行版,适用于桌面和服务器。
  • Arch Linux:一个面向Linux发烧友的发行版,它提供了最新的软件和功能。

Linux 常用命令

  • ls:列出当前目录下的文件和子目录。
  • cd:切换当前工作目录。
  • pwd:显示当前工作目录的路径。
  • mkdir:创建一个新目录。
  • rm:删除文件或目录。
  • cp:复制文件或目录。
  • mv:移动或重命名文件或目录。
  • cat:查看文件内容。
  • grep:在文件中搜索指定的文本。
  • tar:打包和压缩文件和目录。
  • ssh:通过SSH协议远程连接到另一台计算机。

Linux 如何管理用户权限

  • 用户和组命令:Linux提供了命令行工具,如useradd、userdel、usermod和groupadd、groupdel、groupmod等,用于管理用户和组。
  • 文件和目录权限:Linux使用文件和目录权限来控制用户对文件和目录的访问。权限包括读、写和执行权限,可以使用chmod命令来更改权限。
  • Sudo:Sudo是一种工具,允许普通用户以超级用户的权限执行命令。可以使用visudo命令来编辑sudoers文件,以控制哪些用户可以使用sudo。

Linux 系统调用

Linux系统调用是 Linux 内核提供的接口,允许用户程序与内核进行交互并访问操作系统资源,如文件、网络、进程、内存等。Linux 系统调用可以使用 C 语言的标准库函数进行调用,通常使用 syscall() 函数封装系统调用。

常用的 Linux 系统调用:

  1. open():打开一个文件,返回一个文件描述符。
  2. close():关闭一个文件,释放文件描述符。
  3. read():从一个打开的文件描述符中读取数据。
  4. write():向一个打开的文件描述符中写入数据。
  5. stat():获取一个文件的元数据(如文件类型、大小、时间戳等)。
  6. fork():创建一个新进程,复制当前进程的所有内容。
  7. execve():用新程序替换当前进程的内容。
  8. wait():等待一个子进程结束。
  9. exit():退出当前进程。
  10. getpid():获取当前进程的进程ID。
  11. socket():创建一个网络套接字。
  12. connect():连接到一个远程主机。
  13. bind():将一个套接字绑定到一个本地地址。
  14. listen():监听一个套接字。
  15. accept():接受一个连接请求。
  16. send():向一个套接字发送数据。
  17. recv():从一个套接字接收数据。

Linux 系统调用的完整列表可以在 Linux 手册页中找到。在 Linux 系统中,手册页是文档页面,包含有关系统调用、命令、配置文件和库函数等的详细信息。可以使用 man 命令来查看手册页,例如 “man open” 将显示有关 open() 系统调用的手册页。

Linux 系统调用 demo,使用 Linux 系统调用来读取和写入文件:

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
int fd;
ssize_t ret;
char buf[1024];

// 打开文件
fd = open("test.txt", O_RDONLY);
if (fd == -1)
{
perror("open");
exit(EXIT_FAILURE);
}

// 使用 read() 系统调用,读取文件内容
ret = read(fd, buf, sizeof(buf));
if (ret == -1)
{
perror("read");
exit(EXIT_FAILURE);
}

// 输出读取到的内容
printf("Read %ld bytes from file:\n", ret);
write(STDOUT_FILENO, buf, ret);

// 关闭文件
if (close(fd) == -1)
{
perror("close");
exit(EXIT_FAILURE);
}

// 打开文件
fd = open("output.txt", O_WRONLY | O_CREAT, 0644);
if (fd == -1)
{
perror("open");
exit(EXIT_FAILURE);
}

// 使用 write() 系统调用,写入文件内容
ret = write(fd, buf, ret);
if (ret == -1)
{
perror("write");
exit(EXIT_FAILURE);
}

// 关闭文件
if (close(fd) == -1)
{
perror("close");
exit(EXIT_FAILURE);
}

return 0;
}

这个程序首先打开一个名为 test.txt 的文件,使用 read() 系统调用读取文件内容,然后输出到标准输出。接下来,它打开一个名为 output.txt 的文件,并使用 write() 系统调用将读取到的内容写入文件中。最后,程序关闭两个文件并退出。

系统调用的种类如下:

  • 进程控制(创建和删除)
  • 内存管理(分配和释放)
  • 进程间通信
  • 网络管理
  • 文件系统操作
  • 文件操作(访问设备)

CPU 的模式切换

进程通常运行在 用户模式 下,当通过系统调用想内核发送请求时,CPU 会发生中断事件。也就是说,进程在进行系统调用时,CPU 会 用户模式 切换到 内核模式 ,进程在用户态和内核态之间是串行执行。

进程追踪

1
strace -T hello.log ./hello # 追踪 ./hello 程序执行时的进程详情
1
sar -P ALL 1 1 # 获取进程分别在用户模式和内核模式行运行的时间比例