linux c编程 进程编程(整理)

2019-07-12 23:50发布

(代码来自《嵌入式linux应用程序开发标准教程》) 概览: 第一部份:进程简介 第二部份:进程控制  :命令  函数 第三部份:进程实例:  多进程  守护进程 第四部份:附加材料
linux 进程控制函数大全     http://operatingfocus.bokee.com/3327857.html http://blog.sina.com.cn/s/blog_487df383010009rd.html

进程控制函数简介    http://heould.diandian.com/post/2011-11-16/40027176869 fork函数详解http://z515256164.blog.163.com/blog/static/3244302920122149358550/

第一部份:进程简介 进程是Linux系统的基本调度和管理资源的单位,它是通过进程控制块来描述的。进程控制块包含了进程的描述信息、控制信息以及资源信息,它是进程的一个静态描述。在Linux中,进程控制块中的每一项都是一个task_struct结构。 
在Linux中最主要的进程标识有进程号(PID,Process Idenity Number)和它的父进程号(PPID,parent process ID)。其中PID惟一地标识一个进程。PID和PPID都是非零的正整数。
在Linux中获得当前进程的PID和PPID的系统调用函数为getpid()和getppid(),通常程序获得当前进程的PID和PPID之后,可以将其写入日志文件以做备份。 
另外,进程标识还有用户和用户组标识、进程时间、资源利用情况等 

进程是Linux系统的基本调度和管理资源的单位,它是通过进程控制块来描述的。进程控制块包含了进程的描述信息、控制信息以及资源信息,它是进程的一个静态描述。在Linux中,进程控制块中的每一项都是一个task_struct结构。 
在Linux中最主要的进程标识有进程号(PID,Process Idenity Number)和它的父进程号(PPID,parent process ID)。其中PID惟一地标识一个进程。PID和PPID都是非零的正整数。
在Linux中获得当前进程的PID和PPID的系统调用函数为getpid()和getppid(),通常程序获得当前进程的PID和PPID之后,可以将其写入日志文件以做备份。 
另外,进程标识还有用户和用户组标识、进程时间、资源利用情况等 
进程三种状态  就绪 执行 等待

第二部份:进程控制 常用命令    http://www.cnblogs.com/sujz/articles/2044456.html
  • at命令:在指定时刻执行指定的命令序列

格式: at [-V] [-q x] [-f file] [-m] time atq [-V] [-q x] atrm [-V] [-q x] job… batch [-V] [-f file] [-m]
  • bg命令:使一个被挂起的进程在后台执行

格式:bg 该命令无参数。 先使用组合键"Ctrl+Z"。然后使用bg命令。如果想直接把这个命令放在后台执行,可以在命令后使用"&"符号: #du -a / | sort -rn > /tmp/du.sorted &
  • fg命令:使一个被挂起的进程在前台执行

格式:fg -[job-spec]
  • jobs命令:显示后台任务的执行情况

格式:jobs [选项] [jobspec…]
  • kill命令:终止一个进程

格式:kill [-s signal |-p] [-a]pid
  • crontab命令:用于安装、删除或者列出用于驱动cron后台进程的任务表。然后,该配置由cron守护进程在设定的时间执行

格式:crontab [-u user] 文件
  • ps命令:查看系统中进程的状态

格式:ps [选项],如ps aux
  • pstree命令:列出当前的进程,以及它们的树状结构

格式:pstree [选项] [pid|user]
  • top命令:显示系统当前的进程状况

格式:top [选项] 说明:top命令和ps命令的基本作用是相同的,都显示系统当前的进程状况。但是top是一个动态显示过程,即可以通过用户按键来不断刷新当前状态。
  • nice命令:改变程序执行的优先权等级

格式:nice [-n <优先等级>][--help][--version][命令] 说明:应用程序优先权值的范围从-20~19,数字越小,优先权就越高。一般情况下,普通应用程序的优先权值(CPU使用权值)都是0,如果让常用程序拥有较高的优先权等级,自然启动和运行速度都会快些。需要注意的是普通用户只能在0~19之间调整应用程序的优先权值,只有超级用户有权调整更高的优先权值(从-20~19)。
  • renice命令:允许用户修改一个正在运行的进程的优先权

格式:renice priority [ [ -p ] pids ] [ [ -g ] pgrps ] [ [ -u ] users ] 说明:renice命令可重新调整正在执行的程序的优先权等级。默认是以程序识别码指定程序,调整其优先权,也可以指定程序群组或用户名称调整优先权等级,并修改所有隶属于该程序群组或用户的程序的优先权。等级范围从-20~19,只有超级用户可以改变其他用户程序的优先权和设置负数等级。普通用户只能对自己所有的进程使用renice命令。
  • sleep命令:使进程暂停执行一段时间

格式:sleep number [选项]
  • nohup命令:用户退出系统之后继续工作

格式:nohup命令 说明:一般退出Linux系统时,会把所有的程序全部结束掉,包括那些后台程序。但有时候,例如,用户正在下载一个很大的文件,但是你因下班或有事需要先退出系统,希望退出系统时程序还能继续执行。这时,我们就可以使用nohup命令使进程在用户退出后仍继续执行。同时这些进程都在后台执行(命令放到后台运行,nohup必须与&操作同时使用),结果则会写到用户自己的目录下的nohup.out文件里。
  • pgrep命令:查找当前运行的进程,并列出匹配给定条件的进程的pid,所有的条件都必须匹配才会被列出

格式:pgrep [选项][程序名]
  • chkconfig命令: 检查,设置系统的各种服务

格式:chkconfig [--add][--del][--list][系统服务]

获取进程id http://blog.csdn.net/jpcfei/article/details/6288467 Linux进程的管理 <一>获取进程信息函数

进程又称任务,是一个动态的使用系统资源、处于活动状态的应用程序。
进程的管理由进程控制块PCB、进程调度、中断管理、任务队列等组成,它是linux文件系统、存储管理、设备管理和驱动程序的基础。
进程控制块PCB中包含了进程的所有信息,主要包括进程PID、进程所占有的内存区域、文件描述符和进程环境等信息。
他用task_struct的数据结构表示,存在于include/linux/sch.h
进程状态及转换
#define TASK_RUNNING 0 //运行状态
#define TASK_INTERRUPTIBLE 1 //等待状态(可被中断)
#define TASK_UNINTERRUPTIBLE 2  //等待状态(不可被中断)
#define TASK_STOPPED 4  //停止状态
#define TASK_ZOMBIE 8  //睡眠状态
#define TASK_DEAD 16  //僵死状态
进程的基本操作,六大类:
1.获取进程信息函数:主要通过读取进程控制块PCB中的信息。
(1)getpid()
功能:用来获取目前进程的进程标识。
定义函数:pid_t getpid(void)
返回值:返回当前进程的进程识别号。
头文件:#include
(2)getppid()
功能:用来获取目前进程的父进程标识。
定义函数:pid_t getppid(void)
返回值:返回当前进程的父进程识别号。
头文件:#include
(3)getpgid()
功能:用来获得参数pid指令进程所属于的组识别号,若参数为0,则返回当前进程的组识别码。
定义函数:pid_t getpgid(pid_t pid)
返回值:执行成功则返回正确的组识别码,若有错则返-1,错误原因存在于errno中。
头文件:#include
(4)getpgrp()
功能:用来获得目前进程所属于的组识别号,等价于getpgid(0)。
定义函数:pid_t getpgrp(void)
返回值:执行成功则返回正确的组识别码。
头文件:#include
(5)getpriotity(void)
功能:用来获得进程,进程组和用户的进程执行优先权。
定义函数:int getpriority(int which,int who)
参数含义:
which:
PRIO_PROCESS   who为进程的识别码
PRIO_PGRP     who为进程的组识别码
PRIO_USER     who为用户识别码
返回值:执行成功则返回当前进程的优先级(-20--20),值越小优先级越高。若出错则返-1,原因在errno中。
头文件:#include
  简单实例: [keven@localhost systemCall]$ cat -n get_process_information.c
     1  #include
     2  #include
     3  #include
     4
     5  int main(/*int argc,char **argv*/)
     6  {
     7          printf("This process's pid is:%d",getpid());
     8          printf("/nThis process's farther pid is:%d",getppid());
     9          printf("/nThis process's group pid is:%d",getpgid(getpid()));
    10          printf("/nThis process's group pid is:%d",getpgrp());
    11          printf("/nThis process's priority is:%d/n",getpriority(PRIO_PROCESS,getpid()));
    12          return 0;
    13  }
[keven@localhost systemCall]$ ./get_process_information
This process's pid is:6172
This process's farther pid is:5681
This process's group pid is:6172
This process's group pid is:6172
This process's priority is:0
[keven@localhost systemCall]$  

进程控制函数 http://yayi.me/doc/Process-Function.html
进程函数-获取进程ID
pid_t getpid(void) 功能:获取本进程ID 
pid_t getppid(void) 功能:获取父进程ID



进程函数-创建子进程
pid_t fork(void) 功能:创建子进程

fork会被调用一次,却返回两次,有三种不同的返回值:
1.在父进程中,fork返回子进程创建的PID.
2.在子进程中,fork返回0.
3.如果出现错误,fork返回一个负值.
注:子进程会复制代码自行运行,子进程中的变量不影响父进程,子进程执行的次序不确定.

pid_t vfork(void) 功能:创建子进程
vfork会被调用一次,却返回两次,有三种不同的返回值:
1.在父进程中,vfork返回子进程创建的PID.
2.在子进程中,vfork返回0.
3.如果出现错误,vfork返回一个负值.
注:子进程与父进程共享数据段,子进程中的变量与父进程保持一致,子进程比父进程优先运行.



进程函数-exec函数
注:exec函数启动一个新的程序,会替换原有的进程,因此进程的PID保持不变. int execl(const char * path , const char * arg1 , ...) 变量 作用 path 被执行程序名(含完整路径) arg1 - argn 被执行程序所需的命令行参数,含程序名.以空指针(NULL)结束.
int execlp(const char * path , const char * arg1 , ...) 变量 作用 path 被执行的程序名(不含路径,将从PATH环境变量中查找该程序) arg1 - argn 被执行程序所需的命令行参数,含程序名.以空指针(NULL)结束.
int execv(const char * path , char * const argv[]) 变量 作用 path 被执行程序名(含完整路径) argv[ ] 被执行程序所需要的命令行参数数组.
int system(const char* string) 功能:调用fork产生子进程,由子进程调用"/bin/sh -c string"來执行参数string所代表的命令与参数.



进程函数-进程等待
pid_t wait(int * status) 功能:阻塞该进程,直到其某个子进程退出.

int pause(void) 功能:pause只有在执行了一个信号处理程序并从其返回时,pause才返回.

守护进程 五步走+出错处理 1,创建子进程,父进程退出 2,setsid() 3,切换目录 4,umask 5,释放文件资源
出错处理syslog   openlog closelog
第三部份:进程编程实例
多进程实例 /* multi_proc.c */ #include #include #include #include #include int main(void) { pid_t child1, child2, child; /*ŽŽœšÁœžö×Óœø³Ì*/ child1 = fork(); /*×Óœø³Ì1µÄ³öŽíŽŠÀí*/ if (child1 == -1) { printf("Child1 fork error "); exit(1); } else if (child1 == 0) /*ÔÚ×Óœø³Ì1Öе÷ÓÃexeclpº¯Êý*/ { printf("In child1: execute 'ls -l' "); if (execlp("ls", "ls", "-l", NULL) < 0) { printf("Child1 execlp error "); } } else /*ÔÚžžœø³ÌÖеȎý×Óœø³Ì2µÄÍ˳ö*/ { child2 = fork(); if (child2 == -1) /*×Óœø³Ì2µÄ³öŽíŽŠÀí*/ { printf("Child2 fork error "); exit(1); } else if( child2 == 0 ) /*ÔÚ×Óœø³Ì2ÖÐʹÆäÔÝÍ£5s*/ { printf("In child2: sleep for 5 seconds and then exit "); sleep(5); exit(0); } printf("In father process: "); child = waitpid(child1, NULL, 0); if (child == child1) { printf("Get child1 exit code "); } else { printf("Error occured! "); } do { child = waitpid(child2, NULL, WNOHANG ); if (child == 0) { printf("The child2 process has not exited! "); sleep(1); } } while (child == 0); if (child == child2) { printf("Get child2 exit code "); } else { printf("Error occured! "); } } exit(0); }

守护进程实例 /* daemon_proc.c */ #include #include #include #include #include #include int main(void) { pid_t child1,child2; int i; /*创建子进程1*/ child1 = fork(); if (child1 == 1) { perror("child1 fork"); exit(1); } else if (child1 > 0) { exit(0); } /*打开日志服务*/ openlog("daemon_proc_info", LOG_PID, LOG_DAEMON); /*以下几步是编写守护进程的常规步骤*/ setsid(); chdir("/"); umask(0); for(i = 0; i < getdtablesize(); i++) { close(i); } /*创建子进程2*/ child2 = fork(); if (child2 == 1) { perror("child2 fork"); exit(1); } else if (child2 == 0) { /*在日志中写入字符串*/ syslog(LOG_INFO, " child2 will sleep for 10s "); sleep(10); syslog(LOG_INFO, " child2 is going to exit! "); exit(0); } else { waitpid(child2, NULL, 0); syslog(LOG_INFO, " child1 noticed that child2 has exited "); /*关闭日志服务*/ closelog(); while(1) { sleep(10); } } }