进程

名词

  • 进程:是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。

  • 线程:是程序执行流的最小单元。调度

  • 进程环境:

    • 其main函数是如何调用;
    • 命令行参数是如何传递给新程序的;
    • 典型的存储空间布局是什么样式;
    • 如何分配另外的存储空间;
    • 进程如何使用环境变量;
    • 进程的各种终止方式
  • 进程控制

    • 新建进程;
    • 执行程序;
    • 进程终止;
    • 实际、有效和保存的用户ID和组ID的控制

方法摘要

函数说明成功失败
进程管理
mainC程序执行
fork创建一个新进程子进程-->0,父进程-->子进程ID(>0)-1
wait获取子进程的终止状态进程ID0或-1
waitpid获取子进程的终止状态进程ID0或-1
execl、execv、execle、execlp、execvp、fexecve启动新的进程
exit程序退出
_Exit程序退出
_exit程序退出
atexit终止处理程序注册0非0
内存分配
malloc存储空间分配非空指针非0
calloc存储空间分配非空指针非0
ralloc存储空间分配非空指针非0
free释放存储空间
环境变量
getenv获取环境值name关联的value的指针,若未找到,返回NULL
putenv设置变量0非0
setenv设置变量0非0
putenv设置变量0-1
getrlimit获取资源限制0非0
setrlimit设置资源限制0非0
进程信息
getpid函数调用进程的进程ID
getppid函数调用进程的父进程ID
getuid函数调用进程的实际用户ID
getgid函数调用进程的实际组户ID
getegid函数调用进程的有效组户ID
setuid设置用户0-1
setgid设置组id0-1
setgid设置组id0-1
nice设置权限值nice=ZERO-1
nice设置权限值nice=ZERO-1
setpriority设置权限值0-1
getpriority获取权限值返回-NZERO~NZERO-1之间的值-1
times设置用户时间返回流逝的墙上时钟时间-1
跳转
setjmp设置跳转点直接调用:0;longjmp:非0
longjmp跳转

名称解释

  • 环境表 :每个程序接受一张环境表(环境都是静态数据)。

    • 一个字符指针数组, 每个指针包涵一个以null结束的C字符串的地址。
    • 环境变量字符串形式: name=value
    • 启动函数
int main(int argc ,char *argv[] ,char *envp[])

'envp':数组指针

输入图片说明

变量说明
COLUMNS终端宽度
DATEMASKgetdate(3)模版文件路径名
HOMEhone起始目录
LANG本地名
LC_ALL本地名
LC_COLLATE本地排序名
LC_CTYPE本地字符分类名
LC_MESSAGES本地消息名
LC_MONETARY本地货币编辑名
LC_NUMERIC本地数字编辑名
LC_TIME本地日期/时间格式名
LINES终端高度
LOGNAME登录名
MSGVERBfmtmsg(3)处理的消息组成部分
NLSPATH消息类模块序列
PATH搜索可执行文件的路径前缀列表
PWD当前工作目录的绝对路径名
SHELL用户首选的shell名
TERM终端类型
TMPDIR在其中创建临时文件的目录路径名
TZ时区信息
  • C程序的存储空间布局

输入图片说明

  • size: 查看正文段、数据段、bss段的长度
size /bin/sh

   text    data     bss     dec     hex  filename
 902580   35984   22920  961484   eabcc  /bin/sh
 
  • 共享库

    • 使可执行文件中不再需要包含公用的库函数,只需要在所有进程都可引用的存储区中保存这种库例程的一个副本。
    • 程序第一次执行或这第一次调用某个库函数时,用动态连接方法将程序共享库函数相链接。
    • 减少了可执行文件的长度,增加了一些运行时时间开销。
    • 可用库函数的新版本代替老版无需对该库的程序重新链接编辑。
  • 进程标识:每个进程都有一个非负整数表示的唯一进程ID。

    • PID=0:调度进程(交换进程)。
    • PID=1:init进程。字自举过程结束时,由内核调用(/sbin/init)。读取与系统有关的初始化文件(/etc/rc*、/etc/inittab、/etc/init。d)。init进程决不会终止,是一个用户进程,以超级用户特权运行。是所有孤儿进程的父进程
  • 进程终止

    • 从main返回
    • 调用exit
    • 调用_exit或_Exit
    • 最后一个线程从其它启动历程返回
    • 最后一个线程调用 pthread_exit
  • 进程异常终止

    • 调用abort;
    • 接受到一个信号
    • 最后一个线程对取消请求做响应
  • 父进程先终止

    • 子进程的父进程都改为init进程。一个进程终止时,内核逐个检测所有活动进程,判断是否有终止进程的子进程。如果有,则子进程的父进程ID更改为1(init进程ID)。
    • init进程只要有一个进程终止,init就会调用一个wait函数取得其终止状态。
  • 竞争条件(race condition)

    • 为了避免竞争条件和轮询,在多个进程之间需要有某种形式的信号发送和接受方法:uninx信号机制,进程间通信 (IPC)
  • 登录

    • 终端登录:/etc/ttys

函数

main : C程序开始执行
 int main(int argc, char *argv[]);
  • 参数:

    • argc : 命令行参数的数目
    • argv : 参数各个指针所构成的数组
  • 特点:

    • 在调用main前线调用一个特殊的启动例程,可执行程序文件将 启动例程 指定为程序的起始地址--这是由编译器设置的,而连接编辑器由C编译器调用。启动例程从内核取得命令行参数和环境变量值,然后为按上述方式调用启动main函数做好安排。

    • 命令行参数。

      • argv[0] :可执行文件名
      • argv[1] :第一个参数
      • argv[2] :第二个参数
exit、_Exit、_exit :退出
#include <stdlib.h> 'ISO C'

void exit(int status);

void _Exit(int status);

#include <unistd.h> 'POSIX'

void _exit(it status);


//用法
exit(0); = return(0);
  • 参数:

    • status : 终止状态
  • 特点:

    • 将退出状态(exit status)作为参数传送给函数。
    • 父进程先终止
atexit :终止处理程序
#include <stdlib.h>

int atexit(void (*func)(void));
        -- '成功:0;出错:非0'
        
  • 参数:

    • (*func) :函数地址
  • 特点:

    • 终止处理程序的顺序与它们登记(注册)时的顺序相反
    • 登记多次,调用多次。

输入图片说明

存储空间分配
#include <stdlib.h>

void *malloc(size_t size);

void *calloc(size_t nobj,size_t size);

void *ralloc(size_t *ptr, size_t newsize);
        -- '成功:非空指针;出错:NULL'
        
void *free(void *ptr);

  • 特点:

    • malloc:分配指定字节数的存储区。
    • calloc:分配指定长度的对象存储空间存储空间,每个bit都初始化为0。
    • ralloc增加或减少分配区的长度。
    • free:释放ptr指向的存储空间。
    • 大多数实现分配的存储空间比所要求的要稍大,记录管理信息:分配块的长度、指向下一个分配块的指针
环境变量:getenv、putenv、setenv、unsetenv
#incLude <stdlib.h>

char *getenv(const char *name);

    --'指向与name关联的value的指针;若未找到,返回NULL'
    
  • 特点:

    • ISC O没有定义任何环境变量。
#include <stdlib.h>

int putenv(char *str);
    
        -- '成功:0;失败:非0’' 
        
int setenv(const char *name, const char *value ,int rewrite);

int putenv(const char *str);

        -- '成功:0;出错:-1'
  • 参数:

    • putenv的str: name=value,删除已存在。
    • setenv的rewrite:
      • rewrite=非0 :删除已存在的。
      • rewrite=0 :不操作。
    • str: name=value
  • 特点

    • value :自动通过malloc 变更。
setjmp、longjmp:跳转
#inlude <setjmp.h>

int setjmp(jmp_buf env);

        --'直接调用:0;longjmp:非0'
        
int longjmp(jmp_buf env, int val)

  • 参数:

    • setjmp:

      • jmp_buf:存放在调用longjmp时能用来恢复栈状态的所有信息。因为需要另一个函数中引用env变量,通常将env变量定义为全局变量。
    • longjmp:

      • val:将成为从setjmp处返回的值。
getrlimit、setrlimit:资源限制(一般都是大小)
#include <sys/resources.h>

int getrlimit(int resource, struct rlimit *rlpth);

int setrlimit(int resource, const struct rlimit *rlpth);

    -- '成功:0;出错:非0'

//rlimit 结构

struct rlimit {
    rlim_t rlim_cur; /*软限制:现在真正使用的限制*/
    rlim_t rlim_max; /*硬现在:rlim_cur的最大值*/
}

  • 参数:

    • resouce :
现在说明超过影响
RLIMIT_AS进程总得可用存储空间的最大长度(字节)影响到sbrk、mmap函数
RLIMIT_COREcore文件的最大字节数若其值为0则阻止创建core文件。
RLIMIT_CPUCPU时间的最大值(秒)当超过次软限制时,向进程发送SIGXCPU信号
RLIMIT_DATA数据端的最大字节长度。data+bss
RLIMIT_FSIZE创建文件的最大字节长度超过此软限制,则向该进程发送SIGXFSZ信号
RLIMIT_MEMLOCK一个进程使用mlock(2)能够锁定在存储空间中的最大字节长度
RLIMIT_MSGQUEUE进程为POSIX消息队列分配的最大存储字节
RLIMIT_NOFILE打开的最多文件数影响sysconf函数在参数_SC_OPEN_MAX中的返回值
RLIMIT_NPROC最大子进程数影响sysconf函数在参数_SC_CHILD_MAX中的返回值
RLIMIT_NPTS伪终端的最大数量
RLIMIT_RSS最大驻内存集字节长度(resident set size in bytes,RSS)。
RLIMIT_SBSIZE在任一给定时刻,一个用户可占用的套接字缓冲区的最大长度
RLIMIT_SIGPENDINGE一个进程可排队的信号最大数量影响sigqueue函数
RLIMIT_STACK栈的最大字节数
RLIMIT_SWAP用户可消耗的交换空间的最大字节数
RLIMIT_VMEMRLIMIT_AS
进程信息:
#include <unistd.h>

pid_t getpid(void);
        
        -- '函数调用进程的进程ID'

pid_t getppid(void);

        -- '函数调用进程的父进程ID'

uid_t getuid(void);

        -- '函数调用进程的实际用户ID'

uid_t geteuid(void);

        -- '函数调用进程的有效用户ID'

uid_t getgid(void);

        -- '函数调用进程的实际组户ID'

uid_t getegid(void);

        -- '函数调用进程的有效组户ID'
  • 特点:

    • 实际用户ID:
    • 有效用户ID:
fork : 创建一个新进程
#inlcude <unistd.h>

pid_t fork(void);

        -- '成功:子进程-->0,父进程-->子进程ID(>0);出错:-1'
  • 特点:

    • 执行成功:子进程-->0,父进程-->子进程ID(>0)
    • 父子进程共享正文段(.text).
    • 子进程单独获得(创建) 父进程很多信息副本:
      • 数据空间
      • 堆和栈
      • 文件描述符
      • 实际用户ID,实际组ID,有效用户ID,有效组ID
      • 附属组ID
      • 进程组ID
      • 会话ID
      • 控制终端
      • 设置用户ID标志和设置组ID标志
      • 当前工作目录
      • 跟目录
      • 文件模式创建屏蔽字
      • 信号屏蔽和安排
      • 对任一打开文件描述符的执行时关闭(close-on-exec)标志
      • 环境
      • 存储映像
      • 资源限制
    • 父子进程的区别:
      • fork的返回值不同
      • 进程ID不同
      • 子进程的 tms_utime、tms_stime、tms_cutime和tms_ustime的值设置为0
      • 子进程不继承父进程设置的文件锁。
      • 子进程的为处理闹钟被清除
      • 子进程的未处理信号集设置为空集
    • fork之后经常跟随exec。很多实现并不执行一个父进程数据段、栈和堆的完全副本,作为代替使用了写时复制(Copy-On-Write,COW)
      • 写时复制:将程数据段、栈和堆由父子进程共享,内核将它们的访问权限改变为只读。如果父子进程修改这些区域,内核只为修改区域的那块内存制作一个副本(虚拟存储的以“页”)

输入图片说明

  • 用法
    • 一个父进程希望复制自己,使父子进程同时执行不同的代码。网络服务器进程很常见--父进程等待客户的端的服务请求。当这种请求到达,父进程调用fork,是子进程处理次请求。
    • 一个进程要执行一个不同的成(shell的常见请求)。子进程fork返回后立即调用exec。
vfork:复制一个新进程
  • 特点:

    • 子进程立即exec一个新的进程,vfork不会复制子进程的地址空间。(shell的基本操作)
wait、waitpid:获取子进程的终止状态
#include <sys/wait.h>

pid_t wait(int *statloc);

pid_t waitpid(pid_t pid,int *statloc,int options);

    --'成功:进程ID;出错:0或-1'
  • 参数:

    • waitpid
参数说明
pid
pid-1等待任一子进程。这种情况下:waitpid与wait等效
pid>0等待进程ID与pid相等的子进程
pid0等待组ID等于调用进程组ID的任一子进程
pid<-1等待组ID等于pid绝对值的任一子进程
options
WCONTINUED若实现支持作业控制,那么pid指定的任一子进程在停止后又继续,但其状态尚未报告,则返回状态状态
WNOHANGpid指定的子进程并不是立即可用,则waitpid不阻塞,次数返回值为0
WUNTRACED若实现支持作业控制,那么pid指定的任一子进程在停止后,但其状态尚未报告,则返回状态状态
  • 特点:

    • 所有子进程都在运行,则阻塞
    • 子进程终止,立即返回子进程的终止状态。
    • 没有任何子进程,则立即出错返回。
    • waitpid:有选项,调用者不阻塞。
waitid : 返回终止状态
#include <sys/wait.h>

int waitid(idtype_t idtype,id_t id, siginfo_t *infop, int options);
    
        -- '成功:0;出错:-1'
  • 特点:

    • Single UNIX specification 标准。
exec:创建新的子进程
#include <unistd.h>

int execl(const char *pathname, const char *arg0,.../* (char *)0 */);

int execv(const char *pathname, const char *argv[]);

int execle(const char *pathname, const char *arg0,.../* (char *)0, char *const envp[] */);

int execve(const char *pathname, const char *argv[], char *const envp[] );

int execlp(const char *pathname, const char *arg0,.../* (char *)0 */);

int execvp(const char *pathname, const char *argv[]);

int fexecve(int fd, const char *pathname, const char *argv[]);

  • 特点
    • 子进程单独获得(创建) 父进程很多信息副本:
      • 进程ID和父进程ID
      • 实际用户ID,实际组ID
      • 附属组ID
      • 进程组ID
      • 会话ID
      • 控制终端
      • 闹钟尚余留的时间
      • 当前工作目录
      • 根目录
      • 文件模式创建屏蔽字
      • 信号屏蔽和安排
      • 未处理信号
      • 资源限制
      • nice值
      • tms_utime、tms_stime、tms_cutime以及tms_cstime值
setuid、setgid:设置用户id和组id
#include <unistd.h>

int setuid(uid_t uid);

int setgid(git_t gid);

    -- '成功:0;出错:-1'
system函数:执行脚本命令
#include <stdlib.h>

int system(const char *cmdstring);

getlogin:用户标识

#include <unistd.h>

char *getlogin(void);

    --'成功:返回指向登录名字符串的指针;出错:NULL'

nice、getproiorty、setpriority:权限值

#include <unistd.h>

int nice(int incr);

    --'成功:nice=ZERO;出错:-1'

  • 参数:
    • incr :
      • 最大最小值不能超过系统给定范围。输入超过,则直接设置最大最小值。
      • 出错:errno!=0

#include <sys/resource.h>

int setpriority(int which,id_t who, int value);
    
    -- '成功:0;出错:-1'
    
int getpriority(int which,id_t who);

    -- '成功:返回-NZERO~NZERO-1之间的值;出错:-1'
    
  • 参数:

    • which:
      • PRIO_PROCESS:表示进程。
      • PRIO_PGRP:表示进程组。
      • PRIO_USER: 表示用户ID。
进程时间

#include <sys/times.h>

clock_t times(struct tms *buf);

    --'成功:返回流逝的墙上时钟时间;出错:-1'
    
//tms结构

struct tms {
    clock_t tms_utime;  '用户的CPU时间'
    clock_t tms_stime;  '系统的CPU时间'
    clock_t tms_cutime;  '终止的子进程用户的CPU时间'
    clock_t tms_cstime;  '终止的子进程用户的CPU时间'
}

转载于:https://my.oschina.net/u/2246410/blog/1801953

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值