uc8
来源:互联网 发布:新旧系统数据迁移方案 编辑:程序博客网 时间:2024/05/16 12:44
回顾:
fork() - 通过复制父进程创建子进程,代码区不复制,其他的区域都会复制。如果有文件描述符,只复制描述符,不复制文件表。fork()创建的子进程和父进程共享代码区。fork()之后父子进程同时运行,fork()并不确定父子进程谁先运行,也不确定谁先结束。
wait() - 父进程等待子进程的结束。如果有多个,任意一个结束就返回。
pid_t wait(int* status)
status包括: 是否正确结束 以及 退出码
WIFEXITED WEXITSTATUS
进程的退出 - 正常退出 和 非正常
exit() _Exit() return 信号
今天:
waitpid()
vfork() + exec系列函数
信号
waitpid()
pid_t waitpid(pid_t pid,int* status,int option)
pid是进程的ID,可以有4种情况:
< -1 等待 进程组ID等于参数绝对值的子进程
-1 等待任意子进程
0 等待 和父进程一个进程组的 子进程
>0 等待 进程ID等于参数的 子进程(指定一个)
status 和 wait参数一样
option 0 代表会一直等待直到有子进程退出(阻塞)
WNOHANG 代表不会等待,有没有子进程退出都返回(非阻塞)
返回值有三种可能:
返回 结束子进程的PID
如果option为WNOHANG,没有子进程结束时返回0
出错 返回 -1.
vfork()用法在语法上和fork()一样,区别:
1 vfork() 不复制 父进程任何的内存空间。
2 vfork() 确保子进程先运行。
vfork()创建的子进程 占用父进程的内存空间运行,父进程 在此时 被阻塞,vfork()要和 exec系列函数结合使用才有 意义。vfork 负责创建子进程,exec系列函数 负责提供 新的程序被执行。当vfork()创建的子进程执行新的程序时,父进程的内存空间就会返回给父进程,父子进程同时运行。
经验:
fork()创建子进程和父进程执行相同的代码。
vfork()创建子进程 执行的代码与父进程无关,而是全新的代码。
exec系列函数不是新建一个进程,而是修改进程。用新的代码区、堆区、栈区、数据区(程序) 替换旧的。
exec系列函数不改变 PID。
创建子进程的方法有两种:
1 fork() - 父子进程执行相同的代码段
2 vfork()+exec系列函数 - 子进程执行完全不同的代码段。
信号(signal)
信号就是程序中断的一种方式,属于软件中断。
中断 就是 终止当前的代码,转而执行其他的代码。
中断有软件中断和硬件中断。
Unix/Linux系统中,可以使用信号中断当前代码,转而执行其他的代码。
常见的信号:
ctrl+c、ctrl+\、段错误、总线错误、浮点数例外
int/0 浮点数例外(出错,程序被信号中断)
double/0 无穷大 (不出错)
信号本质上就是一个整数(非负数),Unix常用信号1-48,Linux常用信号1-64。每个信号都有一个宏名称,便于记忆,宏名称都以SIG开头。比如:
SIGINT就是信号2,ctrl+c 就是信号2
信号的产生是无规律的,不知道什么时候会来,因此对于信号的处理 采用异步处理。
kill 命令就是针对信号,可以发送信号:
kill -信号 进程ID - 给某个进程发信号
kill -l 显示所有的信号
信号是不连续的,有些信号是不存在的。不同的操作系统,对应信号的值有可能不同,因此在开发中,使用信号的宏名字 有更好的通用性。
信号分为可靠信号和不可靠信号两类:
不可靠信号,1-31都是不可靠信号。这种信号不支持排队,有可能丢失。非实时信号
可靠信号,34-64都是可靠信号。这种信号支持排队,不会丢失,是 实时信号。
信号的处理
Unix/Linux对于信号的处理,有三种方式:
1 默认处理 - 80%的默认处理都是中断进程。
2 忽略信号 - 可以忽略信号,不做处理。
3 自定义处理 - 程序员写 信号处理的代码。
注:
信号9 不能被忽略,也不能被 自定义处理。
普通用户只能给自己的进程发信号,但root可以给所用用户发信号。
信号的处理方式 可以使用signal()/sigaction()注册。
函数指针 signal(int 信号,函数指针)
signal 可以设定信号的处理方式,第一个参数是哪个信号,第二个参数是 信号的处理方式,包括:
SIG_IGN - 忽略该信号
SIG_DFL - 默认处理信号
一个程序员自定义的函数名 - 自定义处理信号
错误返回 SIG_ERR
子进程的信号处理
fork()创建的子进程 完全 沿袭父进程对信号的处理方式。父进程忽略子进程也忽略,父进程自定义子进程也自定义。
vfork()+exec 创建的子进程,父进程忽略,子进程也会忽略,但父进程是自定义,子进程会改为默认处理
发信号的方式:
1 键盘发送 (少部分信号)
ctrl+c -> 2 SIGINT
ctrl+\ -> 3 SIGQUIT
ctrl+z -> 20 SIGSTP 暂停进程
2 出错 (少部分信号)
段错误 -> 11 SIGSEGV
总线错误 -> 7 SIGBUS
整数除0 -> 8 SIGFPE
3 命令kill (全部信号)
kill -信号 进程ID
信号0 用来 测试 是否有权限发信号
4 信号发送函数 (全部信号)
raise() kill() alarm() sigqueue() ...
raise()函数 只能给自己所在的进程发信号。
sleep()和usleep()都可以休眠程序,区别:
sleep()被信号打断会返回剩余秒数,usleep()返回-1.
sleep()休眠的单位是秒,usleep()是微秒。
区别:
sleep()被信号打断会返回剩余秒数,usleep()返回-1.
sleep()休眠的单位是秒,usleep()是微秒。
0 0