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
原创粉丝点击