linux系统篇 -- 一、系统概要
文章目录
- 一、linux 系统概要
- 1. 程序
- 1.1 进程
- 1.2 应用程序与外部设备
- 2. 设备驱动程序
- 3. linux 的工作模式
- 4. linux 系统调用(system call)
- 4.1 深入理解系统调用
- 4.2 strace
- 4.3 track 常用选项
linux 系统相关知识, 文章内容来自狄泰软件学院, 如有需要淘宝执自行购买学习.
作者: baron
一、linux 系统概要
计算机系统由 “躯体” 和 “灵魂” 两部分组成
- 躯体:构成计算机系统的电子设备(硬件) --> 中央处理器(CPU)
- 灵魂:指挥躯体完成动作的指令序列 --> 操作系统(OS)
计算任务执行流程
- 通过交互设备或网络像计算机系统发起计算请求
- 根据请求将任务指令加载进入内存
- cpu 从内存中取指令,并逐条执行
- 计算任务的最终结果暂存入内存
- 内存数据通过交互设备或网络进行反馈(也可直接写入外存)
1. 程序
程序的本质是指令和数据的集合。指令是指示 cpu 执行动作的命令, 数据是 cpu 执行动作的目标. 程序的分类:
- 应用程序:用户可以直接使用,为用户提供直接帮助的程序
- 程序中间件:多数应用程序的通过功能,用于辅助应用程序的运行
- 操作系统:直接操作硬件设备,并为应用程序与程序中间件提供运行环境
1.1 进程
进程是程序的执行. 通常情况下, 程序在操作系统上以进程为单位运行. 每个程序运行后由一个或者多个进程构成. 进程是操作系统任务的基本单元, 也是系统资源的基本分配单元. 程序是"死的", 进程是活的. 程序的本质只是二进制数据, 不加载执行就没有任何价值. 进程是计算机系统对程序的一次加载执行, 即:执行计算任务的过程.
1.2 应用程序与外部设备
多数情况下,应用程序需要借助外部设备才能外层计算任务. 外部设备是处cpu与内存之外的其他计算机硬件(如: 硬盘, 网卡, 显卡). 直接访问, 开发成本高, 应用开发者必须熟悉各类外设的硬件特性. 开发周期长, 业务逻辑加设备逻辑. 应用场景难, 其他应用程序可能同事访问外设. 间接访问, 应用程序通过某软件层(驱动程序)接口以统一的方式访问外设.
2. 设备驱动程序
设备驱动程序是外设访问接口, 对应用程序提供统一的外设访问方式. 它象各种外设的共性, 简化设备驱动开发方式. 设备类型有字符设备, 块设备, 网络设备, 等. 对于同一类型的设备, 可以通过统一接口进行访问. 设备驱动程序并非唯一的访问外设的方式. 如何限制进程必须按照规则通过驱动程序访问外部设备? 可以通过工作模式进行限制.
3. linux 的工作模式
linux 系统的工作模式有用户模式和内核模式两种:
- 用户模式(user mode)执行应用程序私有代码, 受限制的访问内存, 无法直接访问外部设备.
- 内核模式执行内核代码,可以访问所有的硬件资源, 可立即暂停进程的执行.对大多数设备驱动程序属于内核模式.
内核职责: 以统一的方式有序的分配硬件资源, 保证用户任务按照预期的方式执行.
4. linux 系统调用(system call)
应用程序与操作系统内核直接的接口(表现形式为函数). 系统调用决定了应用程序如何与内核打交道.它解决了以下问题
- 系统资源有限, 需要统一有序的调配.
- 多个进程可能同时访问同一资源, 进而产生冲突.
- 一些特定的功能必须由操作系统内核完成(如: 精确延时).
进程系统调用后, 由用户模式切换到内核模式(执行内核代码). 工作模式的转变通常由中断触发(不同于普通的函数调用). 用户进程通过系统调用请求内核完成资源分配, 硬件访问等操作. 所有进程请求集中到内核, 内核可以统一调度处理, 协调进程的执行.
4.1 深入理解系统调用
模式切换是系统调用的本质, 系统模式切换依赖于 cpu 提供的工作方式, 一般来说, 大部分 cpu 至少有两种工作方式.
- 高特权级, 可以访问任意数据, 包括外围设备, 比如网卡, 硬盘等.
- 低特权级, 只能首先访问内存, 并且不允许访问外围设备, 可被打断.
系统模式切换通过执行特殊的 cpu 指令发起(int 0x80). 应用程序(进程)无法直接切换 cpu 的工作方式. 系统调用是应用程序(进程)请求模式切换的唯一方式.下面实例使用系统调用打印字符串
void print(const char*s, int l);
void exit(int code);void program()
{print("Hello World!\n", 13);exit(0);
}// 使用系统调用打印字符串
void print(const char*s, int l)
{asm volatile ("movl $4, %%eax\n" // 制定编号为 4 的系统调用(sys_wirte)"movl $1, %%ebx\n" // 指定 sys_write 的输出目标, 1 为标准输出"movl %0, %%ecx\n" // 指定输出字符地址"movl %1, %%edx\n" // 指定输出字符串长度"int $0x80 \n" // 执行系统调用: : "r"(s), "r"(l) // 参数: "eax", "ebx", "ecx", "edx"); // 保留寄存器, 不用于关联变量
}// 退出当前进程
void exit(int code)
{asm volatile ("movl $1, %%eax\n""movl %0, %%ebx\n""int $0x80 \n": : "r"(code): "eax", "ebx"); }运行结果:
Hello World!
编译命令注释如下:
gcc -m32 -e program -fno-builtin -nostartfiles program.c
-m32 : 采用 32 位编译
-e program : 指定函数入口
-fno-builtin -nostartfiles : 不链接到 start 函数
4.2 strace
strace 是系统调用工具它具有以下功能:
- 用于判断应用程序是否触发系统调用.
- 用于监控进程与内核的交互(监控系统调用).
- 用于追踪进程内部状态(定位运行时的问题).
- 按序输出进程运行过程想通调用名称, 参数和返回值.
实例分析如下
strace -o ./program.log ./a.out // 使用 strace 工具查看 a.out 这个程序的系统调用.execve("./a.out", ["./a.out"], 0x7ffcc94c5760 /* 23 vars */) = 0 // 用来加载执行应用程序, 使其变成进程, 返回值为 0
/* ============> 参数分析 */
// pid : 进程号
// execve : 系统调用的名称, 用来加载执行应用程序, 使其变成进程
// ("./a.out", ["./a.out"], 0x7ffd160fcea0 /* 23 vars */) : 系统调用的参数
// = 0: 系统调用的返回值.
/* ============> 结束 */brk(NULL) = 0x56ca1000 // 创建应用程序所需的数据段
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xf7f8e000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
set_thread_area({entry_number=-1, base_addr=0xf7f8e9c0, limit=0x0fffff, seg_32bit=1, contents=0, read_exec_only=0, limit_in_pages=1, seg_not_present=0, useable=1}) = 0 (entry_number=12)
mprotect(0x56581000, 4096, PROT_READ) = 0
write(1, "Hello World!\n", 13) = 13 // 往标准输出(屏幕), 写入字符串 "Hello World!\n" , 长度为13
exit(0) = ?
+++ exited with 0 +++
使用标准方式打印 "Hello World!\n"
#include <stdio.h>int main()
{printf("Hello World\n");return 0;
}运行结果:
Hello World!
使用 strace 查看系统调用过程
execve("./a.out", ["./a.out"], 0x7ffdda4b7c80 /* 23 vars */) = 0 // 用来加载执行应用程序, 使其变成进程, 返回值为 0
brk(NULL) = 0x557d7ea3b000 // 创建应用程序所需的数据段
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=103208, ...}) = 0
mmap(NULL, 103208, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f5b96694000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\240\35\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030928, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f5b96692000
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f5b96094000
mprotect(0x7f5b9627b000, 2097152, PROT_NONE) = 0
mmap(0x7f5b9647b000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f5b9647b000
mmap(0x7f5b96481000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f5b96481000
close(3) = 0
arch_prctl(ARCH_SET_FS, 0x7f5b966934c0) = 0
mprotect(0x7f5b9647b000, 16384, PROT_READ) = 0
mprotect(0x557d7d3f5000, 4096, PROT_READ) = 0
mprotect(0x7f5b966ae000, 4096, PROT_READ) = 0
munmap(0x7f5b96694000, 103208) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
brk(NULL) = 0x557d7ea3b000
brk(0x557d7ea5c000) = 0x557d7ea5c000
write(1, "Hello World\n", 12) = 12 // 往标准输出(屏幕), 写入字符串 "Hello World!\n" , 长度为13
exit_group(0) = ?
+++ exited with 0 +++
为什么采用标准方式系统调用会多很多, 因为标准方式是基于 c 标准库来做的, 中间有很多复杂的调用是我们看不见的. 同理 c++ 的结果将更为复杂.
4.3 track 常用选项
-t
在前面打印出调用的实时时间-tt
在前面, 更精确的打印出调用的实时时间-T
在后面打印出调用函数花费的时间-c
打印出调用的次数与总时间 ------ 最常用-s
更详细的展示数据内容, 后跟要展示的数据长度-x
涉及到的数据,优先以字符串的方式进行展示, 以16进制的数据进行展示-xx
涉及到的数据强制以16进制的数据进行展示-e
只关注某个系统调用, 后跟要关注的系统调用函数-e trace=
只关注 trace 后根的系统调用,例如trace=file,read,write
strace -c -o ./program.log ./program.out------ ----------- ----------- --------- --------- ----------------0.00 0.000000 0 1 execve
------ ----------- ----------- --------- --------- ----------------
100.00 0.000000 1 total
System call usage summary for 32 bit mode:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------0.00 0.000000 0 1 write0.00 0.000000 0 2 2 access0.00 0.000000 0 1 brk0.00 0.000000 0 1 mprotect0.00 0.000000 0 1 mmap20.00 0.000000 0 1 set_thread_area
------ ----------- ----------- --------- --------- ----------------
100.00 0.000000 7 2 total
编译形语言的效率比解释行语言的效率高.
linux系统篇 -- 一、系统概要相关推荐
- Linux高级篇——IO系统编程
1.文件IO 2.标准IO 3.动静态库的制作 4.目录IO 1.文件IO 文件IO简介 涉及哪些接口? Input ,Output 是从用户空间角度考虑的输入与输出: 从内核读取数据或从文件中读取数 ...
- windows制作docker镜像_电脑技术之Windows系统篇-PE系统的制作及GHO镜像系统恢复
技术的道路,永无止步,没有了进步它就为退步! 如果您是大牛,这篇文章您可以略过! 首先我们先来了解下PE系统,以下是百度百科的介绍! Windows PE_百度百科baike.baidu.com W ...
- 利用自己的电脑设置web服务器建网站_win7系统篇,win7系统利用iis搭建web服务器实现信息浏览资源共享的操作方法...
很多小伙伴都遇到过对win7系统利用iis搭建web服务器实现信息浏览资源共享进行设置的困惑吧,一些朋友看过网上对win7系统利用iis搭建web服务器实现信息浏览资源共享设置的零散处理方法,并没有完 ...
- ESP32-C3入门教程 系统篇①——FreeRTOS系统时钟Tick
文章目录 一.前言 二.延时函数 三.计时函数 四.源码详解 一.前言 本文基于VS Code IDE进行编程.编译.下载.运行等操作 基础入门章节请查阅:ESP32-C3入门教程 基础篇①--基于V ...
- 高通平台开发系列讲解(系统篇)系统关机流程
文章目录 一.关机流程图 二.执行关机流程 2.1.kernel_shutdown_prepare流程 2.2.migrate_to_reboot_cpu流程 2.3.syscore_shutdown ...
- Linux系统篇-文件系统虚拟文件系统
看了之前的关于Linux内存管理和进程调度的文章,相比读者们应该对Linux有了大致的了解,本文的主题是Linux虚拟文件系统.闲话少说,开始! 1.软链接和硬链接的区别 我们知道文件都有文件名与数据 ...
- NUC 折腾笔记 - Linux 系统篇
NUC 折腾笔记 - Linux 系统篇 写一篇迟到的折腾笔记:NUC8 8i5beh .原本计划折腾 Hackintosh ,最后折腾了一台 Linux Homelab 设备. 本篇记录 NUC 基 ...
- Linux运维-服务器系统篇
Linux运维-服务器系统篇 开篇导读: 本篇博文是此系列教程的第二课,在这一课中将大概的介绍一下服务器上的操作系统,了解一下它的基本概念和发展历程. 服务器系统的概念和作用 如何理解服务器操作系统? ...
- Ubuntu Linux环境搭建|系统篇
说明:本篇以ubuntu Desktop 12.04 for 64位为例 同样适用与11.10等其他版本 一.准备镜像 1. 下载Ubuntu Desktop 12.04 LTS (目前的最新版本 ...
- linux目录无法进入是磁盘坏,linux故障篇:MBR损坏导致无法正常启动系统
由于MBR中包含磁盘分区表记录,如果MBR遭到破坏,系统将无法读取分区表,导致无法挂载分区,即使通过光盘引导的方式也无法挂载,所以必须对分区表进行正确备份并且必须备份到其他磁盘或U盘中.以保证能够读取 ...
最新文章
- Emojify - v2 吴恩达老师深度学习第五课第二周编程作业2
- 《LeetCode力扣练习》第16题 C语言版 (做出来就行,别问我效率。。。。)
- bzoj 1058: [ZJOI2007]报表统计 (Treap)
- 准备好跟机器人正面交锋了吗?
- 了解PostCSS原理
- 服务器 设置 将 Tomcat 注册 到系统服务 及使用方法
- 获取运行的class文件,所在的目录
- python requests库详解_python爬虫之路(一)-----requests库详解
- HDU-1013-Digital root
- java多线程下载美女图片
- 使用Git上传本地项目到GitHub
- 有了雀巢智能咖啡机,单身狗离“秀恩爱”还会远吗?
- 高数-----两个重要的极限
- Apache 安装虚拟主机
- Autodesk 2013 免费下载 及所有产品product Key(产品密匙)
- POJ3159 Candies(差分约束)
- 函数中arguments是什么?
- 成为JAVA(高级)工程师,该学什么?
- 从tushare获取场内ETF基金数据
- Ansi,UTF8,Unicode,ASCII编码的区别
热门文章
- 转载 解密蓝牙mesh系列 | 第五篇 【好友(Friend)和低功耗节点(LPN)】【友谊(Friendship)参数】【友谊建立】【友谊(Friendship)消息传送】【安全性】【友谊终止】
- 【内存泄露】LeakCanary常见问题
- 在数组中 找左边都比其小右边都比其大的元素
- 写乐100道练习题_写乐大型21K详细评测(文长慎入)
- 枸杞的功效与食用方法
- 一般纳税人企业如何合理避税?
- RabbitMQ消息确认机制和消息重发机制
- 结构体中元素引用—— “.“ 与 “->“
- UVA 1647 Computer Transformation
- [FAST 2009]Cumulus:File System Backup to the Cloud