Skip to content

Commit 8004315

Browse files
committed
线程(部分)
1 parent 0418ec3 commit 8004315

File tree

4 files changed

+90
-9
lines changed

4 files changed

+90
-9
lines changed

chapter10/10.2.md

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
每个进程都有一些属性,`os` 包提供了一些函数可以获取进程属性。
44

5+
## 进程 ID
6+
7+
每个进程都会有一个进程ID,可以通过 `os.Getpid` 获得。同时,每个进程都有创建自己的父进程,通过 `os.Getppid` 获得。
8+
59
## 进程凭证
610

711
Unix 中进程都有一套数字表示的用户 ID(UID) 和组 ID(GID),有时也将这些 ID 称之为进程凭证。Windows 下总是 -1。
@@ -97,6 +101,45 @@ func main() {
97101

98102
此外,`os` 还提供了获取辅助组 ID 的函数:`os.Getgroups()`
99103

104+
### 操作系统用户
105+
106+
`os/user` 允许通过名称或 ID 查询用户账号。用户结构定义如下:
107+
108+
```
109+
type User struct {
110+
Uid string // user id
111+
Gid string // primary group id
112+
Username string
113+
Name string
114+
HomeDir string
115+
}
116+
```
117+
`User` 代表一个用户帐户。
118+
119+
在 POSIX 系统中 Uid 和 Gid 字段分别包含代表 uid 和 gid 的十进制数字。在 Windows 系统中 Uid 和 Gid 包含字符串格式的安全标识符(SID)。在 Plan 9 系统中,Uid、Gid、Username 和 Name 字段是 /dev/user 的内容。
120+
121+
`Current` 函数可以获取当前用户账号。而 `Lookup``LookupId` 则分别根据用户名和用户 ID 查询用户。如果对应的用户不存在,则返回 `user.UnknownUserError ``user.UnknownUserIdError`
122+
123+
```
124+
package main
125+
126+
import (
127+
"fmt"
128+
"os/user"
129+
)
130+
131+
func main() {
132+
fmt.Println(user.Current())
133+
fmt.Println(user.Lookup("xuxinhua"))
134+
fmt.Println(user.LookupId("0"))
135+
}
136+
137+
// Output:
138+
// &{502 502 xuxinhua /home/xuxinhua} <nil>
139+
// &{502 502 xuxinhua /home/xuxinhua} <nil>
140+
// &{0 0 root root /root} <nil>
141+
```
142+
100143
## 进程的当前工作目录
101144

102145
一个进程的当前工作目录(current working directory)定义了该进程解析相对路径名的起点。新进程的当前工作目录继承自其父进程。
@@ -161,13 +204,13 @@ import (
161204
162205
func main() {
163206
fmt.Println("The num of environ:", len(os.Environ()))
164-
gctrace, ok := os.LookupEnv("gctrace")
207+
godebug, ok := os.LookupEnv("GODEBUG")
165208
if ok {
166-
fmt.Println("gctrace==", gctrace)
209+
fmt.Println("GODEBUG==", godebug)
167210
} else {
168-
fmt.Println("gctrace not exists!")
169-
os.Setenv("gctrace", "2")
170-
fmt.Println("after setenv:", os.Getenv("gctrace"))
211+
fmt.Println("GODEBUG not exists!")
212+
os.Setenv("GODEBUG", "gctrace=1")
213+
fmt.Println("after setenv:", os.Getenv("GODEBUG"))
171214
}
172215
173216
os.Clearenv()
@@ -176,14 +219,14 @@ func main() {
176219
177220
// Output:
178221
// The num of environ: 25
179-
// gctrace not exists!
180-
// after setenv: 2
222+
// GODEBUG not exists!
223+
// after setenv: gctrace=1
181224
// clearenv, the num: 0
182225
```
183226

184227
另外,`ExpandEnv``Getenv` 功能类似,不过,前者使用变量方式,如:
185228

186-
os.ExpandEnv("$gctrace") 和 os.Getenv("gctrace") 是一样的。
229+
os.ExpandEnv("$GODEBUG") 和 os.Getenv("GODEBUG") 是一样的。
187230

188231
实际上,`os.ExpandEnv` 调用的是 `os.Expand(s, os.Getenv)`
189232

chapter10/10.3.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# 10.3 线程 #
2+
3+
与进程类似,线程是允许应用程序并发执行多个任务的一种机制。一个进程可以包含多个线程。同一个程序中的所有线程均会独立执行相同程序,且共享同一份全局内存区域。
4+
5+
同一进程中的多个线程可以并发执行。在多处理器环境下,多个线程可以同时并行。如果一个线程因等待 I/O 操作而遭阻塞,那么其他线程依然可以继续运行。
6+
7+
在 Linux 中,通过系统调用 `clone()` 来实现线程的。从前面的介绍,我们知道,该系统调用也可以用来创建进程。实际上,从内核的角度来说,它并没有线程这个概念。Linux 把所有的线程都当作进程来实现。内核并没有准备特别的调度算法或是定义特别的数据结构来表征线程。相反,线程仅仅被视为一个使用某些共享资源的进程。所以,在内核中,它看起来就是一个普通的进程(只是该进程和其他一些进程共享某些资源,如地址空间)。
8+
9+
在 Go 中,通过 `clone()` 系统调用来创建线程,其中的 `clone_flags` 为:
10+
11+
```
12+
cloneFlags = _CLONE_VM | /* share memory */
13+
_CLONE_FS | /* share cwd, etc */
14+
_CLONE_FILES | /* share fd table */
15+
_CLONE_SIGHAND | /* share sig handler table */
16+
_CLONE_THREAD /* revisit - okay for now */
17+
```
18+
19+
也就是说,父子俩共享了地址空间(_CLONE_VM)、文件系统资源(_CLONE_FS)、文件描述符(_CLONE_FILES)和信号处理程序(_CLONE_SIGHAND)。而 `_CLONE_THREAD` 则会将父子进程放入相同的线程组。这样一来,新建的进程和父进程都叫做线程。
20+
21+
22+
23+
24+
# 导航 #
25+
26+
- 上一节:[进程属性和控制](10.2.md)
27+
- 下一节:[进程间通信](10.4.md)
28+

chapter10/10.4.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# 10.3 进程间通信 #
2+
3+
进程之间用来相互通讯和同步
4+
5+
# 导航 #
6+
7+
- 上一节:[创建进程](10.1.md)
8+
- 下一节:[进程间通信](10.3.md)
9+

preface.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
* 第十章 [进程、线程与 goroutine](chapter10/10.0.md)
4444
- 10.1 [创建进程](chapter10/10.1.md)
4545
- 10.2 [进程属性和控制](chapter10/10.2.md)
46-
- 10.3 [进程间通信](chapter10/10.3.md)
46+
- 10.3 [线程](chapter10/10.3.md)
47+
- 10.4 [进程间通信](chapter10/10.4.md)
4748
* 第十一章 网络通信与互联网 (Internet)
4849
* 第十二章 email
4950
* 第十三章 应用构建、debug 与测试

0 commit comments

Comments
 (0)