原创 进程控制开发

2009-5-22 10:06 3176 14 14 分类: MCU/ 嵌入式

掌握进程相关的基本概念<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


程序是一个静态的概念,进程是一个动态的概念,是程序执行的过程。


Linux最主要的标识有进程号(PID)和它的父进程号(PPID),获得PIDPPID的函数分别为getpidgetppid


进程可以分为执行态、就绪态、等待态。


 


掌握linux下的进程结构


linux下的进程分为数据段、代码段和堆栈段,其中,数据段用来存放数据、全局变量及动态分配的空间等。代码段用来存放代码。堆栈段用来存放局部变量跟子程序返回地址及子程序的参数。


 


掌握linux下的进程创建及进程管理


linux进程管理包括启动进程和调度进程。


启动进程包括手动启动跟调度启动。


调度进程: pstopnicerenicekillcrontabbg 等函数。 


进程创建函数


1fork()


有两个返回值


返回0    当前进程是子进程   (就是子进程的返回值为0


返回大于0,当前进程是父进程,返回的值就是子进程的ID(父进程的返回值为子进程ID)


返回-1,     出错。


fork函数得到的子进程是父进程的一个复制品,得到父进程的大部分内容。子进程把所独有的只有它的进程号、资源使用和定时器等。由于复制了父进程的数据段、代码段、堆栈段等大部分内容,所以fork的执行速度并不快。


Fork使用:


Result=fork();


If(result==-1) //出错


{


   perror(“fork error!”);


   exit(1);


}


else if(result==0) //子进程


{


  printf(“child process!”);


}


else //result>0 父进程


{


  printf(“father process!”);


}


 


2exec系列函数


创建进程后的进程执行函数


提供了一个在进程中启动另一个程序执行的方法。


本系列共有6个函数


execl(const char *path,const char *arg…)


execv(const char *path,const char *argv[])


execle(const char *path,const char *arg,…,const char *envp[])


execve(const char *path,const char *argv[],const char *envp[])


execlp(const char *file,const char *arg…)


execvp(const char *file,const char *argv[])


返回为-1,出错


其中,前四个exec为公共,


第五个字母若为”l”,表示是逐个列举方式(list),语法char *arg,若为”v”,则表示是所有参数整体构造指针数组传递(vertor),语法 char *argv[]


第六个字母若为”e”,可以指定当前进程的环境变量。语法char *const envp[]. 若为p,表示文件查找方式可以给出文件名。系统会自己从环境变量中查找。


使用示例:


execl:


execl(“/bin/ps”,”ps”,”-ef”,NULL)


execv:


char *argv[]={“env”,NULL};


execv(“/bin/env”,argv);


 


execle:


char *envp[]={"PATH=/tmp","USR=sunq",NULL};


if(execle("/bin/ps","ps","-ef",NULL,envp)<0)         


 


execve:


char *argv[]={"ps","-ef",NULL};


char *envp[]={"PATH=/tmp","USR=sunq",NULL};


if(execve("/bin/ps",argv,envp)<0)             //execve


 


execlp


if(execlp("ps","ps","-ef",NULL)<0)      //execlp


 


execvp


char *argv[]={"ps","-ef",NULL};


if(execvp("ps",argv)<0)                 //execvp


 


1、 exit_exit


exit退出时做处理


_exit退出时直接退出


 


僵尸进程的概念,请参考僵尸进程详解   僵尸进程详解1


当一个子进程结束后,父进程若还在,则会子进程将会产生僵尸进程。


结束僵尸进程的方法:1、通过waitwaitpid函数来进行。 2、结束父进程,init会自动收尸。


2、  wait waitpid


wait使父进程阻塞,直到子进程结束或者接到一个指定信号。否则一直阻塞。


Waitpid wait作用一样,不过提供更多选项,不一定阻塞,有若干选项。


Wait实例


pc=fork();


if(pc==0)


{


sleep(5);


exit(0);


}


else if(pc>0)


{


printf("child is sleep!\n");


wait(NULL);  //等待子进程退出


printf("child is exited!\n");


}


 


waitpid


pc=fork();


if(pc==0)


{


sleep(5);


exit(0);


}


else if(pc>0)


{


printf("child is sleep!\n");


waitpid(pc,NULL,0);  //等待子进程退出


printf("child is exited!\n");


}


 


 


掌握linux下进程创建相关的系统调用


 


掌握守护进程的概念


守护进程是通常所说的daemon进程,是linux的后台服务进程,通常独立于控制终端周期性执行或者等待某种事物。


如果不想让一个进程不因为用户或者终端或者其它所改变而改变,则必须设置为守护进程。


 


掌握守护进程的启动方法


 


掌握守护进程的输出及建立方法


建立一个守护进程的步骤:


1、  建立子进程、父进程退出


pc=fork(); //建立子进程


if(pc>0)  //退出父进程


exit(0);


 


2、  建立新会话


由于用fork建立子进程时大多复制的父进程的内容,所以


需完成以下任务:


脱离原终端控制


脱离原进程组的控制


脱离原会话组的控制


脱离函数:setsid


成功返回进程组ID,失败返回-1


   isetsid();


 


 


3、  改变当前目录为根目录


因为在工作的时候目录所在的文件系统是不能被卸载的。例:如果当前守护进程工作在/mnt/usb中,那么如果现在想卸载/mnt/usb,则会出现无法卸载的情况。所以,把目录定位到根目录下则不会出现这种情况。除非有人想卸载根目录^_^


函数:chdir


chdir();


                 


4、  重设文件权限掩码


umask(0);


 


5、  关闭文件描述符


for(i=0;I<MAXFILE,I++)


close(i);


 


守护进程的出错处理


为了解决守护进程无法调试的问题,所以可以把出错信息发送到系统的日志文件中。


方法:使用守护进程syslogd来维护的syslog服务,向日志文件/var/log/messages中输出相关信息来完成调试(注:在/etc/syslog.conf中可以配置不同的消息发向何处)


该机制提供了三个syslog函数:openlog,syslog,closelog.


Openlog


void openlog( char *ident, int option, int  facility) 


打开系统日志服务的一个连接


option 
       
用於openlog()option参数可以是以下几个的组合


LOG_CONS : 如果送到system logger时发生问题,直接写入系统console 


LOG_NDELAY : 立即开启连接(通常,连接是在第一次写入讯息时才打开的) 


LOG_PERROR :  将讯息也同时送到stderr 
       LOG_PID :  
PID含入所有讯息中 


facility 
       facility
参数用来指定何种程式在记录讯息,这可让设定档来设定何种讯息如何处理。 
       LOG_AUTH : 
安全/授权讯息(别用这个,请改用LOG_AUTHPRIV) 
       LOG_AUTHPRIV : 
安全/授权讯息 
       LOG_CRON : 
时间守护进程专用(cronat) 
       LOG_DAEMON : 
其它系统守护进程
       LOG_KERN : 
核心讯息 
       LOG_LOCAL0
LOG_LOCAL7 : 保留 
       LOG_LPR : 
行打印机子系统 
       LOG_MAIL : mail
邮件子系统 
       LOG_NEWS : USENET 
新闻子系统 
       LOG_SYSLOG : syslogd
内部所产生的讯息 
       LOG_USER(default) : 
一般使用者等级讯息 
       LOG_UUCP : UUCP
子系统 


syslog


void syslog( int priority, char *format, ...) 


向日志文件中写入消息


priority
       
决定讯息的重要性.  以下的等级重要性逐次递减
       LOG_EMERG : 
系统无法使用 
       LOG_ALERT : 
必须要立即采取反应行动 
       LOG_CRIT : 
重要状况发生 
       LOG_ERR : 
错误状况发生 
       LOG_WARNING : 
警告状况发生 


       LOG_NOTICE : 一般状况,但也是重要状况 
       LOG_INFO : 
资讯讯息 
       LOG_DEBUG : 
除错讯息


closelog


void closelog( void ) 


关闭系统日志服务的连接



 例:见书上P231.或者网络相关资料


学会编写多进程程序


学会编写守护进程


 


总结:


注意forkexec系列、exit_exitwaitwaitpid等函数的用法


注意僵尸进程的概念以及如何销毁僵尸进程


学会编写守护进程,并且用syslog的方法调试


注意ps命令的用法,用来查看进程情况,本章用到ps ps –ef ps –ax ,其余可查网络。

进程的执行顺序?
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
14
关闭 站长推荐上一条 /3 下一条