刚把《unix环境高级编程》看完,就迫不及待的写几篇

文章记录一下相关的知识点。我觉得总共就这个几个方面
进程、线程,io(系统io,c库函数,再来点通信io)。现在
先来一发通过接口控制进程的生命周期。


进程基本知识

我们写源码编译成可执行文件,我们运行可执行文件生成进程

进程处理我们job,跟用户打交道的就是进城了。每个进程都有自己
的进程标识(非负整数)是唯一的,但是进程标示是可以复用的
当一个进程结束后它的进程id就可以被别的新进程使用。当然了每
个进程也有自己的进程空间,进程空间大家都很熟悉了,进程空间
采用虚拟存储技术,让我们可以运行大于我们内存的程序。内存空间
主要:进程环境变量,进程栈, 匿名内存分配 ,堆,未初始化全局变量
初始化全局变量,正文(程序)。总的来说进程和程序的区别就是进程
是动态的并且包含程序的内容,程序是静态的就是一个文件。

进程创建

进程的创建过程就是pcb创建(分配资源)并且插入到就绪队列的过程。

在unix中我们使用的 是 fork 函数

1
2
3
#include <unistd.h>
pid_t fork(void);
返回值:子进程返回0,父进程返回子进程ID;若出错,返回-1

fork 子进程复制父进程进程空间但是共享正文部分,文件描述符也复制

就相当于执行了 dup 函数一样。

进程结束

正常结束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <stdlib.h>
void exit(int status);
void _Exit(int status);
#include <unistd.h>
void _exit(int status);
其中exit函数结束之前,会调用fflush函数,冲洗缓冲区 _Exit _exit 函数
不冲洗缓冲区直接结束进程。
main 函数中的return 相当于exit 函数,效果一样。
```
# 父进程阻塞等待子进程结束
```
#include <sys/wait.h>
pid_t wait(int *statloc);
pid_t waitpid(pid_t pid, int *statloc, int options);
俩个函数返回值:若成功返回进程id,若出错返回0
参数: statloc 为NULL 则标示不关注终止进程状态,
整形指针 指向结束子进程的状态地址
在一个子进程终止前,wait使其调用者阻塞
```
# 进程阻塞
```
#include <unistd.h>
int pause(void);
返回值:-1,errno 设置为 EINTR
只有执行了一个信号处理程序并从其返回时,pause才返回。在这种情况下
pause返回-1, errno 设置为EINTR。
unsigned int alarm(unsigned int seconds);
返回值:0或以前设置的闹钟时间的余留秒数
sleep(int seconds) ;这个函数大家应该都很熟悉吧,那大家有木有自己
写过这个函数,或者知道这个函数是怎么实现的呢,其实我们可以通过alarm
这个函数定时,然后让进程阻塞(pause),时间到之后唤醒进程就可以达到sleep的效果
不过因为涉及到了信号的处理需要考虑竞度问题,因为alarm时间到了之后系统
会给你发出信号,信号处理完之后会继续执行pause之后的。下面是一个简单的例子
unsigned int sleep1(unsigned int seconds)
{
if (signal(SIGALRM, sig_alrm) == SIG_ERR)
return(seconds);
alarm(seconds); /* start the timer */
pause(); /* next caught sinal wakes us up */
return(alarm(0)); /* turn off timer, return unslept time */
}
```
# 进程唤醒
进程的阻塞一般使用 pause函数,pause函数会在进程处理完一个信号程序并返回时
才返回,也就是唤醒进程, 所以唤醒一个进程最简单的办法就是在pause之前,给进程
注册一个信号,然后使用kill函数给该进程发送一个注册过的信号
#include <signal.h>
int kill<pid_pid, int signo);
raise(int signo);
                返回值:若成功返回0,出错返回-1
rasie 向自身发送信号 raise(signo) == kill(getpid(), signo)

pid > 0  将信号发送给进程id为pid的进程
pid == 0 将信号发送给与发送进程同一个进程组的所有进程(具有权限)
pid <  0 将信号发送给其进程组id等于pid绝对值的进程组的所有进程(具有权限)
pid == -1 将信号发送给发送进程有权限向他们发送信号的所有进程。 

```