Linux/UNIX 系统编程手册 - 笔记

Linux/UNIX系统编程手册-基本概念

2020-01-10  本文已影响0人  妖小灰

Linux/UNIX系统编程手册

[德] Michael Kerrisk

第2章 基本概念
第3章 系统编程概念

基本概念

内核

内核的职责:(Tasks performed by the kernel)

内核态和用户态(Kernel mode and user mode)

现代处理器架构一般允许CPU至少在两种不同状态下运行,即:用户态和内核态(或supervisor mode)。执行硬件指令可使CPU在两种状态间来回切换。与之对应,可将虚拟内存区域划分为用户空间和内核空间。在用户态下运行时,CPU只能访问被标记为用户空间的内存;当运行于内核态时,CPU既可以访问用户空间内存,也能访问内核空间内存。

shell

单根目录层级、目录、链接及文件

每个目录至少包含两条记录:...,前者时指向目录本身的链接,后者是指向其上级目录的链接。

文件I/O模型

UNIX系统I/O模型最为显著的特性之一是其I/O通用性概念。也就是说,同一套系统调用(open(), read(), write(), close()等)所执行的I/O操作,可用于所有文件类型,包括设备。

I/O系统调用使用文件描述符(file descriptor)--数值很小的非负整数--来指代打开的文件。获取文件描述符的常用手法是调用open(),在参数中指定I/O操作目标文件的路径名。

进程(Process)

进程是正在执行的程序实例。执行程序时,内核会将程序代码载入虚拟内存,为程序变量分配空间,建立bookkeeping数据结构,以记录与进程有关的各种信息(进程ID,用户ID,组ID以及终止状态)。
内核为各个进程分配计算机资源,在其生命周期内对进程的资源做统筹和调整,进程结束时,释放资源,供其他进程使用。

进程的内存布局(Process memory layout)

创建进程和执行进程

进程使用系统调用fork()来创建一个新进程。调用fork()的进程被称为父进程,新创建的进程被称为子进程。内核通过对父进程的复制来创建子进程。

子进程可以使用系统调用execve()去加载并执行一个全新程序。execve()会销毁现有的文本段、数据段、栈、堆,并根据新程序的代码,创建新segments来替换他们。

每一个进程都有一个唯一的整型进程标识符(PID), 以及一个父进程标识符(PPID).

可使用两种方式来终止一个进程:

The init process

> $ man init
SYSTEMD(1)                                                                            
NAME
       systemd, init - systemd system and service manager

SYNOPSIS
       systemd [OPTIONS...]

       init [OPTIONS...] {COMMAND}

DESCRIPTION
       systemd is a system and service manager for Linux operating systems. When run as first process on boot (as PID 1), it acts as init system that brings up and maintains userspace
       services.

守护进程(Daemon processes)

Examples of daemon processes include syslogd, which records messages in the system
log, and httpd, which serves web pages via the Hypertext Transfer Protocol
(HTTP).

环境列表(Environment list)

每一个进程都有一份环境列表,即在进程用户空间内存中维护的一组环境变量。可使用exportprintenv命令来创建和查看当前进程的环境变量。

$ export [MYVAR='Hello world']

$ printenv
使用unset,命令撤销一个环境变量

进程间通讯及同步(Interprocess Communication and Synchronization)

Linux提供了丰富的进程间通讯(IPC)机制:

信号(Signals)

信号也常被称为“软件中断”。进程收到信号,就意味着某个事件或者异常情况发生。信号有很多类型,分别表示不同的事件和情况。每种信号类型通过不同的整数加上SIGxxx来标识自己。
内核、其他进程或者进程自身均可向进程发送信号。
内核向进程发送信号:

线程(Threads)

每一个进程都可以执行多个线程。可将线程想象为共享同一虚拟内存及一些其他属性的进程。每个线程都会执行相同的程序代码,共享同一数据区域和堆。可是每个线程都有自己的栈,用来装载本地变量和函数调用链接信息。
线程之间可以通过共享的全局变量进行通讯。
多线程应用能从多处理器硬件的并行处理中获益匪浅。

进程组和shell任务控制(Process Group and Shell Job Control)

shell执行的每个程序都创建一个新进程。例如,shell创建了3个进程来执行一下管道命令

& ls -l | sort -k5n | less

主流的shell都提供了一种交互式特性,名为任务控制。shell会将管道内的所有进程置于一个新进程组或任务中,进程组都具有相同的进程组标识符(某个进程的进程ID)。

/proc文件系统

/proc文件系统时一种虚拟文件系统,以文件系统目录和文件形式,提供一个指向内核数据结构的接口。这位查看和改变各种系统属性开启了方便之门。此外,还能通过一组以/proc/PID形式命名的目录查看系统中运行各行程的相关信息。

系统编程概念

系统调用(system call)

系统调用允许进程向内和请求服务。与用户空间的函数调用相比,哪怕是最简单的系统调用都会产生显著的开销,其原因时为了执行系统调用,系统需要临时性的切换到内核态。此外,内核还需验证系统调用的参数、用户内存和内核内存之间也有数据需要传递。

在Linux上,一般情况下,使用glibc作为C语言标准库的实现。

原文链接
https://sun2y.me/

上一篇下一篇

猜你喜欢

热点阅读