1.进程查看命令ps
(1)ps -ajx:偏向显示各种有关的ID
(2)ps -aux:偏向显示进程的各种占用资源
2.向进程发送信号命令kill
(1)kill -信号编号 进程ID,向一个进程发送一个信号
(2)kill -9 xxx,向xxx这个进程发生9号信号,也就是结束这个进程
3.何为守护进程
(1)daemon
(2)长期运行(一般是开机运行直到关机)
(3)与控制台脱离(关闭终端不会结束该进程,这个问题还在与会话)
(4)服务器(server)服务器就是一个一直在运行的程序,可以提供我们某种服务(譬如nfs给我们提供nfs服务通信方式),当我们需要需要这种服务时可以调用服务程序(和服务器程序通信得到服务程序帮助)来进程这种服务操作,服务程序一般都实现为守护进程。
4.常见的守护进程
(1)syslogd:系统日志守护进程,提供syslogd功能
(2)cron:实现操作系统的时间管理,linux中实现定时执行程序的功能要用到cron。
5.编写简单的守护进程
(1)任何一个进程都可以将自己实现成一个守护进程
(2)create_daemon函数要素实现以下六点就可以将一个进程变为守护进程
(2.1)子进程等待父进程退出
(2.2)子进程调用setsid创建新的会话期,脱离控制台
(2.3)调用chdir将当前工作目录设为/
(2.4)umask设置为0以取消任何文件权限屏蔽
(2.5)关闭所有文件描述符
(2.6)将0、1、2定位到/dev/null
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
//函数的作用就是把调用该函数的进程变为守护进程
void creat_daemon()
{
pid_t pid = 0;
pid = fork();
if(pid < 0)
{
perror("fork");
}
//父进程
else if(pid > 0)
{
exit(0);
exit(-1);
}
//子进程
//pid_t setsid(void);
pid = setsid(); //将当前进程设置为新的会话期,目的就是让当前进程脱离控制台
if(pid < 0)
{
perror("setsid");
exit(-1);
}
//将当前目录设置为根目录
//int chdir(const char *path);
chdir("/");
//umask设置为0确保将来进程有最大的文件操作权限
//mode_t umask(mode_t mask);
umask(0);
//关闭所有文件描述符
//先获取当前系统中所允许打开的最大文件描述符数目
//long sysconf(int name);
int cnt = sysconf(_SC_OPEN_MAX);
for(int i;i<cnt;i++)
{
close(i);
}
//打开0、1、2文件描述符定位到/dev/null(垃圾堆目录)
open("/dev/null",O_RDWR);
open("/dev/null",O_RDWR);
open("/dev/null",O_RDWR);
}
int main(void)
{
creat_daemon();
while(1)
{
printf("I am running\n");
sleep(1);
}
return 0;
}
6.使用syslogd来记录调试信息
(1)openlog、syslog、closelog
void openlog(const char *ident, int option, int facility);
void syslog(int priority, const char *format, ...);
void closelog(void);
(2)各种参数
(3)编程实战:一般log信息都在操作系统的、var/log/message这个目录中存在,在ubuntu中在/var/log/syslog文件中
#include <stdio.h>
#include <syslog.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
printf("my pid = %d\n",getpid());
//void openlog(const char *ident, int option, int facility);
openlog("a.out",LOG_PID|LOG_CONS,LOG_USER);
//void syslog(int priority, const char *format, ...);
syslog(LOG_INFO,"this is my log info");
syslog(LOG_INFO,"this is another log info");
//void closelog(void);
closelog();
}
7.syslog工作原理
(1)操作系统有一个守护进程syslogd(开机运行,关机结束),这个守护进程syslogd负责进行日志文件的写入和维护。
(2)syslogd是独立于我们任何一个程序而运行的。我们当前进程和syslogd进程本来是没有任何关系的,但是当前可以调用openlog可以打开一条和syslogd相连接的通道,然后通过syslog向syslogd发消息,然后由syslogd来将其写入到日志文件系统中。
(3)syslogd其实就是一个日志文件系统的服务器进程,提供日志服务,任何需要写日志的进程都可以通过/openlog/syslog/closelog这三个函数利用syslogd提供的日志服务。
8.让程序不能被多次运行
(1)因为守护进程是长时间运行而不退出,因此./a.out执行一次就有一个守护进程,执行多次就有多个进程。
(2)这样并不是我们希望的,我们守护进程一般都是服务器,多次运行可能造成错误。
(3)因此我们希望程序有一个单例运行的功能,如果这个程序之前有这个程序的进程在运行则本次运行直接退出(提示程序已经在运行)
(4)实现方法:用一个文件的存在与否来做标志,当我们启动这个进程时,如果这个标志文件存在则表明进程已经在运行,反之亦然。当程序结束时去删除这个标志文件,这个标志文件要古怪一些,确保不会和电脑中已存在的文件重复。
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#define FILE "./aston_test_single"
void delete_file(void)
{
remove(FILE);
printf("删除成功\n");
}
int main()
{
//程序执行之初判断文件是否处在
int fd = -1;
fd = open(FILE,O_RDWR|O_TRUNC|O_CREAT|O_EXCL,0664);
if(fd < 0)
{
if(errno == EEXIST)
{
printf("进程已存在请不要重复执行\n");
return -1;
}
}
atexit(delete_file); //注册进程清理函数
for(int i=0;i<10;i++)
{
printf("I am running...%d\n",i);
sleep(1);
}
return 0;
}