From 95e4bdc217e02567b5ff9f263ec3336430bb9833 Mon Sep 17 00:00:00 2001 From: shzhxh Date: Sun, 8 Dec 2019 14:41:18 +0800 Subject: [PATCH] =?UTF-8?q?update=20OS=20:=20Openthos=20and=20xv6=EF=BC=8C?= =?UTF-8?q?update=20some=20cmds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OS/Openthos/启动过程.md | 93 ++++++++++++++++++++++------------ OS/XV6/xv6的启动过程.md | 7 ++- Software/docker.md | 13 +++-- Software/getenforce.md | 5 ++ Software/git命令/git-push.md | 3 +- Software/包管理/apt-file.md | 37 ++++++++++++-- 6 files changed, 114 insertions(+), 44 deletions(-) create mode 100644 Software/getenforce.md diff --git a/OS/Openthos/启动过程.md b/OS/Openthos/启动过程.md index d2f8f9b..78f7b2c 100644 --- a/OS/Openthos/启动过程.md +++ b/OS/Openthos/启动过程.md @@ -48,11 +48,15 @@ init是第一个进程,也叫root进程或所有进程的父进程。在此阶 ##### init进程第一阶段 -1. 依据第一个参数进行跳转,并设置环境变量 +1. 依据程序名进行跳转,就是先决定要跑哪个程序 - 如果第1个参数是ueventd,则执行`ueventd_main`,进行设备节点的创建和权限设定。 + argv[0]是当前运行程序的名称,当前运行程序的名称有可能是init, modprobe, uenventd或watchdogd。其中,modprobe、uenventd和watchdogd都是指向init的软链接。 - 如果第1个参数是watchdogd,则执行`watchdogd_main`,用于系统出问题时重启系统。 + 如果当前运行的程序名是modprobe,则执行`modprobe_main`,应该是用来加载内核模块的。 + + 如果当前运行的程序名是ueventd,则执行`ueventd_main`,进行设备节点的创建和权限设定。 + + 如果当前运行的程序名是watchdogd,则执行`watchdogd_main`,用于系统出问题时重启系统。 如果REBOOT_BOOTLOADER_ON_PANIC,则`install_reboot_signal_handlers`,将一些信号的标志设置为SA_RESTART,一旦监听到这些信号则执行重启操作。 @@ -60,9 +64,9 @@ init是第一个进程,也叫root进程或所有进程的父进程。在此阶 由于INIT_SECOND_STAGE是在is_first_stage里定义的,这就确保了is_first_stage只能执行一次。 -2. 挂载文件系统并创建目录 +2. 挂载文件系统并创建目录,Linux需要有这些文件系统才能运行 - `umask(0)`用于清空文件权限。 + `umask(0)`用于清空文件默认权限。这样才能保证后面代码里对文件权限的设置生效了,否则有可能被umask()的设置给屏蔽掉。 在根目录上建立initramdisk所需的基本文件系统(文件系统的其它部分是在随后的rc文件里建立的)。 @@ -74,7 +78,7 @@ init是第一个进程,也叫root进程或所有进程的父进程。在此阶 3. 初始化日志输出,挂载分区设备 - InitKernelLogging用于初始化日志系统,它首先把输入输出重定向到/sys/fs/selinux/null,然后调用InitLogging初始化日志系统。 + InitKernelLogging用于初始化日志系统,它首先把stdin,stdout,stderr重定向到/sys/fs/selinux/null,这样printf或其它打印的函数都输出不了,就不会引发异常了(因为在这个阶段,printf函数是不能用的,会引发错误)。然后调用InitLogging初始化日志系统,这是把init进程的log打印到内核printk的log buffer,因为这个时候没有shell,不能进行通用的log输出,借助内核的功能是较好的选择。 DoFirstStageMount用于初始化特定设备并挂载。 @@ -104,11 +108,11 @@ init是第一个进程,也叫root进程或所有进程的父进程。在此阶 keyctl_get_keyring_ID用于初始化进程会话密钥。KEY_SPEC_SESSION_KEYRING表示获取当前进程的会话密钥,1表示如获取不到则创建一个。 - 在`/dev`目录下创建文件`.booting`,表示booting正在进行中(可以在init.rc里看到,当booting结束会删除此文件)。 + 在`/dev`目录下创建文件`.booting`,这个文件仅仅起到标志的作用,表示系统正在启动(可以在init.rc里看到,当booting结束会删除此文件)。 property_init用于初始化属性系统,并从指定文件读取属性。 - > property_init调用__system_property_area_init实现其功能。 + > property_init调用__system_property_area_init实现其功能。详见bionic/libc/include/sys和bionic/libc/bionic/system_properties.cpp process_kernel_dt和process_kernel_cmdline分别处理dt(设备树)和命令行属性,设备树中参数的优先级总是高于命令行。 @@ -166,23 +170,24 @@ init是第一个进程,也叫root进程或所有进程的父进程。在此阶 bootmode是个全局静态变量,用来标示启动模式,android的启动模式分为正常开机流程和关机充电流程。 -3. 触发所有的事件并不断监听新的事件 +##### init进程第二阶段之服务处理 - 之前的工作是建立各种各样的事件,并没有去触发。只有在本while循环里才真正的触发所有的事件,并用epoll不断监听新的事件。 +init进程作为1号进程是永不退出的,这里的while(true)循环就保证了这一点。 - 如要执行关机命令,则通过`HandlePowerctlMessage()`来执行之。 +之前的工作是建立各种各样的事件,并没有去触发。只有在本while循环里才真正的触发所有的事件,并用epoll不断监听新的事件。 - 当没有属性设置且没有Server开始运行时,才通过`am.ExecuteOneCommand()`从current_executing_actions\_列表里执行一个command,由于外部是一个无限循环,所以current_executing_actions\_列表里的每个command都会执行一遍。这样的条件设定是为了保证属性设置和Server启动的完整性。 +1. 如要执行关机命令,则通过`HandlePowerctlMessage()`来执行之。 - 当没有属性设置且没有Server开始运行时: +2. 当没有属性设置且没有Server开始运行时,才通过`am.ExecuteOneCommand()`从current_executing_actions\_列表里执行一个command,由于外部是一个无限循环,所以current_executing_actions\_列表里的每个command都会执行一遍。这样的条件设定是为了保证属性设置和Server启动的完整性。 +3. 当没有属性设置且没有Server开始运行时: - 如系统不是正在关机,执行`restart_processes()`来判断当前Server是否需要重启,如需重启则执行重启操作。 - 如有进程需要重启,设置`epoll_timeout_ms`的值 - 如有其它command需要执行,则将`epoll_timeout_ms`设置为0以立即唤醒。 - `epoll_wait`用于监听事件的产生,参数`epoll_fd`是由前面的`epoll_create1()`创建的epoll的文件描述符,参数`ev`用于保存事件信息,参数`epoll_timeout_ms`是等待时间 +4. `epoll_wait`用于监听事件的产生,参数`epoll_fd`是由前面的`epoll_create1()`创建的epoll的文件描述符,参数`ev`用于保存事件信息,参数`epoll_timeout_ms`是等待时间 - 如未监听到事件,则向log系统添加一条监听失败的信息;如监听到事件,则直接执行`ev.data.ptr()`(即epoll_ctl注册时的回调函数)。 +5. 如未监听到事件,则向log系统添加一条监听失败的信息;如监听到事件,则直接执行`ev.data.ptr()`(即epoll_ctl注册时的回调函数)。 #### step5: Zygote @@ -282,7 +287,7 @@ Zygote启动系统服务,即ZygoteInit类里的startSystemServer方法。 系统服务运行起来后,引导完成,此时会发送开机启动广播`ACTION_BOOT_COMPLETED` -#### 附录:Android Init Language +#### 附录:init语言 详见:system/core/init/README.md @@ -290,8 +295,10 @@ Zygote启动系统服务,即ZygoteInit类里的startSystemServer方法。 从整体来看,一个rc文件是由若干个段组成的。一个段只能是Actions或Server其中之一: -- Actions,其中Commands和trigger是对Actions的补充。 -- Servers,其中Options是对Servers的补充。 +- Actions,由trigger和它下面的一堆Commands组成。 +- Servers,由一堆Options组成。 + +注意:Actions和Servers不能重名。如果重名了,后出现的定义将会作为错误而忽略掉。 ##### .rc文件 @@ -301,7 +308,7 @@ init language用在.rc文件中,它可能出现在系统中的多个位置。 ##### Actions -Actions就是触发器加一串命令,触发器用来决定是否执行一个Action。如果满足了触发器的条件且action还不在运行队列里,则这个action会被加到运行队列的尾部。 +Actions就是触发器(trigger)加一串命令(commands),触发器用来决定是否执行一个Action。如果满足了触发器的条件且action还不在运行队列里,则这个action会被加到运行队列的尾部。 运行的格式如下: @@ -332,26 +339,49 @@ name是程序名,pathname是程序所在的路径,argument是程序的参数 Options是Services的修改器,它们影响init进程如何运行service以及何时运行service。 - console,此服务需要一个console。默认设备为`/dev/console`。也可自己指定,如`console /dev/tty0`,其中`/dev/`是可忽略的,即等同于`console tty0`。 + - ctitical,此服务是一个设备关键服务。如果在4分钟内退出4次,设备将会重启进入recovery模式。 -- disabled,此服务无法通过它的类来启动,必须通过它的名字来启动。 + +- disabled,此服务无法通过它所属的类型(class)来启动,必须通过它的名字来启动。这就意味着启动一个类型的服务时这种服务是不会被启动的,也就是它被disable掉了。 + - setenv,在启动的进程里设置环境变量。 -- socket,创建一个unix域socket,并将它的fd传给启动的进程。 + +- socket \ \ \ [\ [\]] + + 创建一个unix域socket,它的名字叫/dev/socket/\,并将它的fd传给启动的进程。 + - file,打开一个文件并将它的fd传给启动的进程。 -- user,在执行服务前改变用户名。 + +- user,在执行服务前改变用户(user),默认的用户是root。 + - group,在执行服务前改变组名。 + - capabilities,在执行服务的时候设置capabilities. + - seclabel,在执行服务前改变为seclabel。 + - oneshot,当服务退出后不要重启它。 -- class,为服务指定所属的类。在同一个类里的服务可以同时打开或关闭。如不使用此选项明确指定服务所属的类,则默认在default类里。 + +- class,为服务指定所属的类型。在同一个类型里的服务可以同时打开或关闭。如不使用此选项明确指定服务所属的类型,则默认在default里。 + - animation,将会包含所有启动和关闭animation所必须的服务。 + - onrestart当服务重启的时候执行一条命令。 + - writepid,当子进程forks的时候将其pid写到给定文件中。 + - priority,调度service进程的优先级。 + - namespace,当forking一个服务的时候,进入一个新的PID或挂载namespace。 + - oom_score_adjust,设置子进程的变量值。 + - memcg.swappiness,设置子进程的变量值。 + - memcg.soft_limit_in_bytes,设置子进程的变量值。 + - memcg.limit_in_bytes,设置子进程的变量值。 + - shutdown,设置关机的时候此service进程的行为。默认是关机进程通过传递SIGTERM和SIGKILL来杀死此服务。 ##### Triggers @@ -477,10 +507,7 @@ Triggers就是个字符串,用来匹配特定事件和触发一个action。分 > restarting, otherwise, it just starts the service. `restorecon [ \* ]` -> Restore the file named by _path_ to the security context specified -> in the file\_contexts configuration. -> Not required for directories created by the init.rc as these are -> automatically labeled correctly by init. +> 将所代表的文件恢复到安全上下文里,这个安全上下文是在file_contexts配置中指定的。init.rc创建的目录不需要执行这个命令,因为init会自动正确地标记它们。 `restorecon_recursive [ \* ]` > Recursively restore the directory tree named by _path_ to the @@ -502,7 +529,7 @@ Triggers就是个字符串,用来匹配特定事件和触发一个action。分 > Set the rlimit for a resource. `start ` -> Start a service running if it is not already running. +> 如果一个服务还没有运行则启动它。 > Note that this is _not_ synchronous, and even if it were, there is > no guarantee that the operating system's scheduler will execute the > service sufficiently to guarantee anything about the service's status. @@ -516,7 +543,7 @@ Triggers就是个字符串,用来匹配特定事件和触发一个action。分 `stop ` -> Stop a service from running if it is currently running. +> 如果一个服务正在运行则关闭它。 `swapon_all ` > Calls fs\_mgr\_swapon\_all on the given fstab file. @@ -553,9 +580,7 @@ Triggers就是个字符串,用来匹配特定事件和触发一个action。分 > immediately. `write ` -> Open the file at _path_ and write a string to it with write(2). -> If the file does not exist, it will be created. If it does exist, -> it will be truncated. Properties are expanded within _content_. +> 把写到里。里的属性将会展开。 ##### Imports @@ -564,4 +589,6 @@ Triggers就是个字符串,用来匹配特定事件和触发一个action。分 #### 参考文档 - [foxleezh/AOSP](https://github.com/foxleezh/AOSP) -- 《深入理解Android卷1》邓凡平 \ No newline at end of file +- 《深入理解Android卷1》邓凡平 +- [freshui/Android init进程分析](https://blog.csdn.net/freshui/article/details/5747199) +- [freshui/Android init脚本解析](https://blog.csdn.net/freshui/article/details/5772564) \ No newline at end of file diff --git a/OS/XV6/xv6的启动过程.md b/OS/XV6/xv6的启动过程.md index 244a9ec..26723fc 100644 --- a/OS/XV6/xv6的启动过程.md +++ b/OS/XV6/xv6的启动过程.md @@ -138,7 +138,7 @@ binit 缓冲区缓存。binit会从一个静态数组buf中构建出一个有NBU 2. 将mepc寄存器写入main函数的地址,这样执行mret指令后会从main函数开始执行。 3. 将satp寄存器写入0,这样就不会开启分页机制,而直接使用的物理地址。 4. 将medeleg和mideleg寄存器写入0xffff,因为medeleg的低16位是有意义的(对应着16个异常),mideleg寄存器的低12位是有意义的,那么这样把两个寄存器的低16位都写入1相当于是把所有的异常和中断的处理都授权给S态了。 -5. 设置计时器中断。 +5. 设置计时器中断。**TODO**:为什么在M态设置计时器中断? 6. 将寄存器mhartid的值写入到寄存器tp。 7. 执行mret指令,进入S特权级,执行main函数。 @@ -186,7 +186,10 @@ binit 缓冲区缓存。binit会从一个静态数组buf中构建出一个有NBU ##### 9. kvminithart -开启分页。 +文件位置:kernel/vm.c,开启分页。 + +- 使用w_satp函数向satp寄存器写入内核页表,其采用的是Sv39的分页方式。 +- 使用sfence_vma函数刷新TLB,这样才能使分页机制真正生效。 ##### 10. procinit diff --git a/Software/docker.md b/Software/docker.md index c642953..cb474b5 100644 --- a/Software/docker.md +++ b/Software/docker.md @@ -141,9 +141,6 @@ commit # 从容器创建一个镜像。 cp diff events -exec # 在运行的容器中执行一个命令。 - -i, --interactive # 始终保持STDIN打开,即使没有附加 - -t, --tty # 分配一个伪TTY export # 将一个容器文件系统输出为压缩文件。 history # 查看某个镜像下的所有层。 import @@ -197,6 +194,16 @@ docker create [options] [cmd] [args] # 创建容器。实际上是为指 -v, --volume list # 本地目录挂载到容器里 ``` +##### exec + +``` +docker exec # 在运行的容器中执行一个命令。 + -i, --interactive # 始终保持STDIN打开,即使没有附加 + -t, --tty # 分配一个伪TTY +``` + + + ##### load ``` diff --git a/Software/getenforce.md b/Software/getenforce.md new file mode 100644 index 0000000..17ba58f --- /dev/null +++ b/Software/getenforce.md @@ -0,0 +1,5 @@ +``` +getenforce # 获取selinux的当前模式 + # 可能的模式有enforcing, permissive, disabled +``` + diff --git a/Software/git命令/git-push.md b/Software/git命令/git-push.md index 86a1db9..7bef312 100644 --- a/Software/git命令/git-push.md +++ b/Software/git命令/git-push.md @@ -17,7 +17,8 @@ git push [选项] [ [...]] ``` -d, --delete # 删除远程仓库的refs。refs可以一个分支,也可以是一个标签。 --f, --force # +-f, --force # 看起来不是“强制推送”这么简单,具体原理待查 +-u, --set-upstream # 指定默认的远程仓库 ``` diff --git a/Software/包管理/apt-file.md b/Software/包管理/apt-file.md index 4809b1c..5a03cd0 100644 --- a/Software/包管理/apt-file.md +++ b/Software/包管理/apt-file.md @@ -1,7 +1,34 @@ -作用:查找库与软件包的神器 -安装:`sudo apt install apt-file` +#### 语法 -使用: +``` +apt-file [options] [pattern] +apt-file [options] -f +apt-file [options] -D +``` -- 安装完后要更新数据库`apt-file update` -- 查找软件包或库的信息`apt-file search xxx` \ No newline at end of file +#### 动作 + +``` +update # 从apt-sources获取内容 +search, find # 查找 +list, show # 列出包里的文件 +``` + +#### 选项 + +##### 模式(pattern)选项 + +``` +-f, --from-file # 从文件读取模式,每行代表一个模式(使用"-"代表从stdin读取模式) +-D, --from-deb # 使用.deb包的文件列表作为模式 +``` + + + +##### 查找选项 + +##### 其它选项 + +#### 使用 + +- 安装完后要更新数据库`apt-file update` \ No newline at end of file