(代码来自《嵌入式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 <unistd.h>
(2)getppid()
功能:用来获取目前进程的父进程标识。
定义函数:pid_t getppid(void)
返回值:返回当前进程的父进程识别号。
头文件:#include <unistd.h>
(3)getpgid()
功能:用来获得参数pid指令进程所属于的组识别号,若参数为0,则返回当前进程的组识别码。
定义函数:pid_t getpgid(pid_t pid)
返回值:执行成功则返回正确的组识别码,若有错则返-1,错误原因存在于errno中。
头文件:#include <unistd.h>
(4)getpgrp()
功能:用来获得目前进程所属于的组识别号,等价于getpgid(0)。
定义函数:pid_t getpgrp(void)
返回值:执行成功则返回正确的组识别码。
头文件:#include <unistd.h>
(5)getpriotity(void)
功能:用来获得进程,进程组和用户的进程执行优先权。
定义函数:int getpriority(int which,int who)
参数含义:
which:
PRIO_PROCESS who为进程的识别码
PRIO_PGRP who为进程的组识别码
PRIO_USER who为用户识别码
返回值:执行成功则返回当前进程的优先级(-20--20),值越小优先级越高。若出错则返-1,原因在errno中。
头文件:#include <sys/resource.h>
简单实例:
[keven@localhost systemCall]$ cat -n get_process_information.c
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/resource.h>
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)功能:创建子进程
1.在父进程中,fork返回子进程创建的PID.
2.在子进程中,fork返回0.
3.如果出现错误,fork返回一个负值.
注:子进程会复制代码自行运行,子进程中的变量不影响父进程,子进程执行的次序不确定.
pid_t vfork(void)功能:创建子进程
1.在父进程中,vfork返回子进程创建的PID.
2.在子进程中,vfork返回0.
3.如果出现错误,vfork返回一个负值.
注:子进程与父进程共享数据段,子进程中的变量与父进程保持一致,子进程比父进程优先运行.
注: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才返回.
第三部份:进程编程实例
多进程实例
/* multi_proc.c */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t child1, child2, child;
/*ŽŽœšÁœžö×Óœø³Ì*/
child1 = fork();
/*×Óœø³Ì1µÄ³öŽíŽŠÀí*/
if (child1 == -1)
{
printf("Child1 fork error\n");
exit(1);
}
else if (child1 == 0) /*ÔÚ×Óœø³Ì1Öе÷ÓÃexeclpº¯Êý*/
{
printf("In child1: execute 'ls -l'\n");
if (execlp("ls", "ls", "-l", NULL) < 0)
{
printf("Child1 execlp error\n");
}
}
else /*ÔÚžžœø³ÌÖеȎý×Óœø³Ì2µÄÍ˳ö*/
{
child2 = fork();
if (child2 == -1) /*×Óœø³Ì2µÄ³öŽíŽŠÀí*/
{
printf("Child2 fork error\n");
exit(1);
}
else if( child2 == 0 ) /*ÔÚ×Óœø³Ì2ÖÐʹÆäÔÝÍ£5s*/
{
printf("In child2: sleep for 5 seconds and then exit\n");
sleep(5);
exit(0);
}
printf("In father process:\n");
child = waitpid(child1, NULL, 0);
if (child == child1)
{
printf("Get child1 exit code\n");
}
else
{
printf("Error occured!\n");
}
do
{
child = waitpid(child2, NULL, WNOHANG );
if (child == 0)
{
printf("The child2 process has not exited!\n");
sleep(1);
}
} while (child == 0);
if (child == child2)
{
printf("Get child2 exit code\n");
}
else
{
printf("Error occured!\n");
}
}
exit(0);
}
守护进程实例
/* daemon_proc.c */ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <sys/wait.h> #include <syslog.h> 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); } } }