掌握进程相关的基本概念
程序是一个静态的概念,进程是一个动态的概念,是程序执行的过程。
Linux最主要的标识有进程号(PID)和它的父进程号(PPID),获得PID和PPID的函数分别为getpid和getppid。
进程可以分为执行态、就绪态、等待态。
掌握linux下的进程结构
linux下的进程分为数据段、代码段和堆栈段,其中,数据段用来存放数据、全局变量及动态分配的空间等。代码段用来存放代码。堆栈段用来存放局部变量跟子程序返回地址及子程序的参数。
掌握linux下的进程创建及进程管理
linux进程管理包括启动进程和调度进程。
启动进程包括手动启动跟调度启动。
调度进程: ps、top、nice、renice、kill、crontab、bg 等函数。
进程创建函数
1、fork()
有两个返回值
返回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!”);
}
1、 exit和_exit
exit退出时做处理
_exit退出时直接退出
当一个子进程结束后,父进程若还在,则会子进程将会产生僵尸进程。
结束僵尸进程的方法:1、通过wait、waitpid函数来进行。 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 : 时间守护进程专用(cron及at)
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.或者网络相关资料
学会编写多进程程序
学会编写守护进程
总结:
注意fork、exec系列、exit、_exit、wait、waitpid等函数的用法
注意僵尸进程的概念以及如何销毁僵尸进程
学会编写守护进程,并且用syslog的方法调试
注意ps命令的用法,用来查看进程情况,本章用到ps 、ps –ef 、ps –ax ,其余可查网络。
进程的执行顺序?
守护进程实例
守护进程实例包括两部分:主程序test.c和初始化程序init.c。主程序每隔一分钟向/tmp目录中的日志test.log报告运行状态。初始化程序中的init_daemon函数负责生成守护进程。读者可以利用init_daemon函数生成自己的守护进程。
以上程序在RedHat Linux6.0下编译通过。步骤如下:
编译:gcc -g -o test init.c test.c
执行:./test
查看进程:ps -ef
从输出可以发现test守护进程的各种特性满足上面的要求。