LINUX进程控制程序设计——进程控制编程2
进程等待
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int * status)
功能:
阻塞该进程,直到其某个子进程退出。
status
1、status是一个整型指针,是该子进程退出时的状态;
2、status若为空,则代表任意状态结束的子进程;
3、status若不为空,则代表指定状态结束的子进程;
4、另外,子进程的结束状态可由linux中一些特定的宏来测定。
6 #include <errno.h>
7
8 int main(void)
9 {
10 pid_t pid, pr;
11
12 pid = fork();
13
14 if(pid == 0)
15 {
16 printf("i am child process pid = %d\n", getpid());
17 sleep(10);
18 }
19 else if(pid > 0)
20 {
21 pr = wait(NULL);
22 printf("child process has exited %d\n", pr);
23 return 0;
24 }
25 else
26 {
27 perror("fork");
28 exit(1);
29 }
30 }
pid_t waitpid(pid_t pid, int *status, int options)
pid
1、pid > 0:只等待进程ID等于pid的子进程,不管已经有其他子进程运行结束退出了,只要指定的子进程还没结束,waitpid就会一直等下去
2、pid = -1:等待任何一个子进程退出,此时和wait作用一样
3、pid = 0:等待其组ID等于调用进程的组ID的任一子进程
4、pid < -1:等待其组ID等于pid的绝对值的任一子进程
option
1、WNOHANG:若由pid指定的子进程不立即可用,则waitpid不阻塞,此时返回值为0
2、WUNTRACED:若实现某支持作业控制,则由pid指定的任一子进程状态已暂停,且其状态自暂停以来还未报告过,则返回其状态
3、0:同wait,阻塞父进程,等待子进程退出
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/wait.h>
4 #include <unistd.h>
5 #include <stdlib.h>
6
7 int main(void)
8 {
9 pid_t pc, pr;
10 pc = fork();
11 if(pc < 0)
12 {
13 perror("fork");
14 exit(1);
15 }
16 else if(pc == 0)
17 {
18 sleep(5);
19 exit(0);
20 }
21 else
22 {
23 do
24 {
25 pr = waitpid(pc, NULL, WNOHANG);
26 if(pr == 0)
27 {
28 printf("the child process has not exited\n");
29 sleep(1);
30 }
31 }while(pr == 0);
32
33 if(pr == pc)
34 printf("child exit pid = %d\n", pr);
35 else
36 printf("some error occured.\n");
37 }
38 return 0;
39 }
守护进程
守护进程(Daemon)是linux中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件。守护进程常常在系统引导装入时启动,在系统关闭时终止。linux系统有很多守护进程,大多数服务都是通过守护进程实现的,同时,守护进程还能完成许多系统任务,例如,作业规划进程crond、打印进程lqd等(这里的结尾字母d就是Daemon的意思)
由于在linux中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。但是守护进程却能够突破这种限制,它从被执行开始运转,直到整个系统关闭时才退出。如果想让某个进程不因为用户或终端或其他变化而受到影响,那么就必须把这个进程编程一个守护进程
创建守护进程的步骤
创建守护进程是可以按一定的流程来实现的,可分为五个步骤:
1、创建子进程,父进程退出
2、在子进程中创建新会话
3、改变工作目录
4、重设文件权限掩码
5、关闭任何不需要的文件描述符
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <fcntl.h>
5 #include <sys/types.h>
6 #include <errno.h>
7 #include <unistd.h>
8 #include <sys/wait.h>
9 #include <sys/stat.h>
10
11 #define MAXFILE 65535
12
13 int main(void)
14 {
15 //第一步:创建子进程,父进程退出
16 int i;
17 int fd;
18 int writenum;
19 char *buf = "this is a Daemon program\n";
20 int len;
21 len = strlen(buf);
22 pid_t pc;
23 pc = fork();
24
25 if(pc < 0)
26 {
27 perror("fork");
28 exit(1);
29 }
30 else if(pc > 0)
31 {
32 exit(0);
33 }
34 //第二步:在子进程中创建新会话
35 setsid();
36 //第三步:改变工作目录
37 chdir("/");
38 //第四步:重设文件权限掩码
39 umask(0);
40 //第五步:关闭任何不需要的文件描述符
41 for(i = 0; i < MAXFILE; i++)
42 {
43 close(i);
44 }
45
46 while(1)
47 {
48 fd = open("/tmp/daemon.log", O_CREAT | O_WRONLY | O_APPEND, 0666);
49 if(fd < 0)
50 {
51 perror("open");
52 exit(1);
53 }
54 writenum = write(fd, buf, len+1);
55 if(writenum < 0)
56 {
57 perror("write");
58 exit(1);
59 }
60 close(fd);
61 sleep(10);
62 }
63 }
守护进程出错处理
一种通用的办法是使用syslog服务,将程序中的出错信息输入到“/var/log/messages”系统日志文件中,从而可以直观地看到程序的问题所在。
注意:“/var/log/message”系统日志文件只能由拥有root权限的超级用户查看。
syslog是linux中的系统日志管理服务,通过守护进程syslogd来维护。该守护进程在启动时会读一个配置文件“/etc/syslog.conf”。该文件决定了不同种类的消息会发送向何处。例如,紧急消息可被送向系统管理员并在控制台上显示,而警告消息则可记录到一个文件中。
#include <syslog.h>
void openlog(char *ident, int option, int facility)
Ident:要向每个消息加入的字符串,通常为程序的名称
option:
1、LOG_CONS:如果消息无法送到系统日志服务,则直接输出到系统控制终端
2、LOG_NDELAY:立即打开系统日志服务的连接。在正常情况下,直到发送到第一条消息时才打开连接
3、LOG_PERROR:将消息也同时送到stderr上
4、LOG_PID:在每条消息中包含进程的PID
facility:指定程序发送的消息类型
1、LOG_AUTHPRIV:安全/授权讯息
2、LOG_CRON:时间守护进程(cron及at)
3、LOG_DAEMON:其他系统守护进程
4、LOG_KERN:内核信息
5、LOG_LOCAL[0-7]:保留
6、LOG_LPR:行打印机子系统
7、LOG_MAIL:邮件子系统
8、LOG_NEWS:新闻子系统
9、LOG_SYSLOG:syslogd内部所产生的信息
10、LOG_USER:一般使用者登记讯息
11、LOG_UUCP:UUCP子系统
#include <syslog.h>
void syslog(int priority, char *format, …)
priority:指定消息的重要性
1、LOG_EMERG:系统无法使用
2、LOG_ALERT:需要立即采取措施
3、LOG_CRIT:有重要情况发生
4、LOG_ERR:有错误发生
5、LOG_WARNING:有警告发生
6、LOG_NOTICE:正常情况,但也是重要情况
7、LOG_INFO:信息消息
8、LOG_DEBUG:调试信息
format
以字符串指针的形式表示输出的格式,类似printf中的格式
#include <syslog.h>
void closelog(void)
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/types.h>
4 #include <errno.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <syslog.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10
11 int main(void)
12 {
13 pid_t pc, sid;
14 int i;
15 int fd;
16 char *buf = "this is my first daemon\n";
17 int len = strlen(buf);
18 int writenum;
19
20 pc = fork();
21 if(pc < 0)
22 {
23 perror("fork");
24 exit(1);
25 }
26 else if(pc > 0)
27 {
28 exit(0);
29 }
30
31 openlog("daemon_update", LOG_PID, LOG_DAEMON);
32 if((sid = setsid()) < 0)
33 {
34 syslog(LOG_ERR, "%s\n", "setsid");
35 exit(1);
36 }
37
38 if((sid = chdir("/")) < 0)
39 {
40 syslog(LOG_ERR, "%s\n", "chdir");
41 exit(1);
42 }
43
44 umask(0);
45
46 for(i = 0; i < 65535; i++)
47 {
48 close(i);
49 }
50
51 while(1)
52 {
53 fd = open("/tmp/daemon.log", O_CREAT | O_WRONLY | O_APPEND, 0666);
54 if(fd < 0)
55 {
56 syslog(LOG_ERR, "%s\n", "open");
57 exit(1);
58 }
59 write(fd, buf, len+1);
60 if(writenum < 0)
61 {
62 syslog(LOG_ERR, "%s\n", "write");
63 exit(1);
64 }
65 close(fd);
66 sleep(10);
67 }
68 closelog();
69 return 0;
70 }