From 80043152ad925a0928a44d0b473cf4fcfaac3ee7 Mon Sep 17 00:00:00 2001 From: polaris Date: Sat, 3 Sep 2016 09:22:34 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BA=BF=E7=A8=8B=EF=BC=88=E9=83=A8=E5=88=86?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chapter10/10.2.md | 59 ++++++++++++++++++++++++++++++++++++++++------- chapter10/10.3.md | 28 ++++++++++++++++++++++ chapter10/10.4.md | 9 ++++++++ preface.md | 3 ++- 4 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 chapter10/10.3.md create mode 100644 chapter10/10.4.md diff --git a/chapter10/10.2.md b/chapter10/10.2.md index bb9b5f0..243e7ec 100644 --- a/chapter10/10.2.md +++ b/chapter10/10.2.md @@ -2,6 +2,10 @@ 每个进程都有一些属性,`os` 包提供了一些函数可以获取进程属性。 +## 进程 ID + +每个进程都会有一个进程ID,可以通过 `os.Getpid` 获得。同时,每个进程都有创建自己的父进程,通过 `os.Getppid` 获得。 + ## 进程凭证 Unix 中进程都有一套数字表示的用户 ID(UID) 和组 ID(GID),有时也将这些 ID 称之为进程凭证。Windows 下总是 -1。 @@ -97,6 +101,45 @@ func main() { 此外,`os` 还提供了获取辅助组 ID 的函数:`os.Getgroups()`。 +### 操作系统用户 + +包 `os/user` 允许通过名称或 ID 查询用户账号。用户结构定义如下: + +``` +type User struct { + Uid string // user id + Gid string // primary group id + Username string + Name string + HomeDir string +} +``` +`User` 代表一个用户帐户。 + +在 POSIX 系统中 Uid 和 Gid 字段分别包含代表 uid 和 gid 的十进制数字。在 Windows 系统中 Uid 和 Gid 包含字符串格式的安全标识符(SID)。在 Plan 9 系统中,Uid、Gid、Username 和 Name 字段是 /dev/user 的内容。 + +`Current` 函数可以获取当前用户账号。而 `Lookup` 和 `LookupId` 则分别根据用户名和用户 ID 查询用户。如果对应的用户不存在,则返回 `user.UnknownUserError ` 或 `user.UnknownUserIdError`。 + +``` +package main + +import ( + "fmt" + "os/user" +) + +func main() { + fmt.Println(user.Current()) + fmt.Println(user.Lookup("xuxinhua")) + fmt.Println(user.LookupId("0")) +} + +// Output: +// &{502 502 xuxinhua /home/xuxinhua} +// &{502 502 xuxinhua /home/xuxinhua} +// &{0 0 root root /root} +``` + ## 进程的当前工作目录 一个进程的当前工作目录(current working directory)定义了该进程解析相对路径名的起点。新进程的当前工作目录继承自其父进程。 @@ -161,13 +204,13 @@ import ( func main() { fmt.Println("The num of environ:", len(os.Environ())) - gctrace, ok := os.LookupEnv("gctrace") + godebug, ok := os.LookupEnv("GODEBUG") if ok { - fmt.Println("gctrace==", gctrace) + fmt.Println("GODEBUG==", godebug) } else { - fmt.Println("gctrace not exists!") - os.Setenv("gctrace", "2") - fmt.Println("after setenv:", os.Getenv("gctrace")) + fmt.Println("GODEBUG not exists!") + os.Setenv("GODEBUG", "gctrace=1") + fmt.Println("after setenv:", os.Getenv("GODEBUG")) } os.Clearenv() @@ -176,14 +219,14 @@ func main() { // Output: // The num of environ: 25 -// gctrace not exists! -// after setenv: 2 +// GODEBUG not exists! +// after setenv: gctrace=1 // clearenv, the num: 0 ``` 另外,`ExpandEnv` 和 `Getenv` 功能类似,不过,前者使用变量方式,如: -os.ExpandEnv("$gctrace") 和 os.Getenv("gctrace") 是一样的。 +os.ExpandEnv("$GODEBUG") 和 os.Getenv("GODEBUG") 是一样的。 实际上,`os.ExpandEnv` 调用的是 `os.Expand(s, os.Getenv)`。 diff --git a/chapter10/10.3.md b/chapter10/10.3.md new file mode 100644 index 0000000..3a39f19 --- /dev/null +++ b/chapter10/10.3.md @@ -0,0 +1,28 @@ +# 10.3 线程 # + +与进程类似,线程是允许应用程序并发执行多个任务的一种机制。一个进程可以包含多个线程。同一个程序中的所有线程均会独立执行相同程序,且共享同一份全局内存区域。 + +同一进程中的多个线程可以并发执行。在多处理器环境下,多个线程可以同时并行。如果一个线程因等待 I/O 操作而遭阻塞,那么其他线程依然可以继续运行。 + +在 Linux 中,通过系统调用 `clone()` 来实现线程的。从前面的介绍,我们知道,该系统调用也可以用来创建进程。实际上,从内核的角度来说,它并没有线程这个概念。Linux 把所有的线程都当作进程来实现。内核并没有准备特别的调度算法或是定义特别的数据结构来表征线程。相反,线程仅仅被视为一个使用某些共享资源的进程。所以,在内核中,它看起来就是一个普通的进程(只是该进程和其他一些进程共享某些资源,如地址空间)。 + +在 Go 中,通过 `clone()` 系统调用来创建线程,其中的 `clone_flags` 为: + +``` +cloneFlags = _CLONE_VM | /* share memory */ + _CLONE_FS | /* share cwd, etc */ + _CLONE_FILES | /* share fd table */ + _CLONE_SIGHAND | /* share sig handler table */ + _CLONE_THREAD /* revisit - okay for now */ +``` + +也就是说,父子俩共享了地址空间(_CLONE_VM)、文件系统资源(_CLONE_FS)、文件描述符(_CLONE_FILES)和信号处理程序(_CLONE_SIGHAND)。而 `_CLONE_THREAD` 则会将父子进程放入相同的线程组。这样一来,新建的进程和父进程都叫做线程。 + + + + +# 导航 # + +- 上一节:[进程属性和控制](10.2.md) +- 下一节:[进程间通信](10.4.md) + diff --git a/chapter10/10.4.md b/chapter10/10.4.md new file mode 100644 index 0000000..6a12916 --- /dev/null +++ b/chapter10/10.4.md @@ -0,0 +1,9 @@ +# 10.3 进程间通信 # + +进程之间用来相互通讯和同步 + +# 导航 # + +- 上一节:[创建进程](10.1.md) +- 下一节:[进程间通信](10.3.md) + diff --git a/preface.md b/preface.md index b2b6956..54d0776 100644 --- a/preface.md +++ b/preface.md @@ -43,7 +43,8 @@ * 第十章 [进程、线程与 goroutine](chapter10/10.0.md) - 10.1 [创建进程](chapter10/10.1.md) - 10.2 [进程属性和控制](chapter10/10.2.md) - - 10.3 [进程间通信](chapter10/10.3.md) + - 10.3 [线程](chapter10/10.3.md) + - 10.4 [进程间通信](chapter10/10.4.md) * 第十一章 网络通信与互联网 (Internet) * 第十二章 email * 第十三章 应用构建、debug 与测试