您的位置:首页 > 其它

6.1 守护进程课后题2015/8/1

2015-08-01 23:31 447 查看

题目:编写监控/home/itcast/目录下文件创建与更改的守护进程,日志文件放在/home/itcast/filechangelog

思路:用链表存储文件列表,到下一个周期在用另一个链表存储新的文件列表,然后两个链表对比,找出那些没变,那些是增加的,那些已经删除了,然后根据这些信息把重新把第一个链表修改好,并且把这些信息写到log中去

本程序主要分为5部分,main代码文件,链表函数文件,function函数文件,头文件,Makefile。

main代码文件

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "defend.h"
#include <dirent.h>
#include <stdlib.h>
#include <errno.h>

#define MAX_PATH 1024

struct list *tmp;
int status = 0; //这个是状态位,主要是来验证链表中的文件元素是不是已经被删除

void daemonize(void)
{
struct list *first; //正常维护的链表
first = creat_list();
struct list *second;    //用来比对文件是否增加或删除的链表
second = creat_list();

pid_t pid;
if ((pid = fork()) < 0)  //创建进程
sys_err("fork");
else if(pid != 0)   //父进程挂掉
exit(0);

setsid();   //修改自身的会话id

if(chdir("/") < 0)  //修改运行目录
sys_err("fork");

umask(0);   //修改权限掩码
close(0);   //0,1,2三个文件描述符重定向到NULL
open("/dev/null", O_RDWR);
dup2(0, 1);
dup2(0, 2);

tmp = first;    //把第一次first的地址给tmp,然后通过load_list函数来加载目录

load_list("/home/itcast");  //第一次加载目录

while(1) {
sleep(600); //运行周期10分钟
status++;   //更改存在状态位
tmp = second;   //加载第二遍目录列表,用来和first链表比对
load_list("/home/itcast"); //加载第二遍
contrast(first, second); //对比两个链表
check_del(first); //把已经删除的文件所对应的first中的链表元素删除
free_list(second);//释放second的内存,方便下次使用

}
}

int main(void)
{
daemonize();

return 0;
}


链表函数文件

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
#include "defend.h"

struct list *creat_list()   //创建链表空间
{
return calloc(sizeof(struct list), 1);
}

void add_list(struct list *ls, char *name, struct stat *st) //添加链表元素
{
struct list *p = ls;
while(p->next) {
p = p->next;
}
struct list *tmp = creat_list();
tmp->next = p->next;
p->next = tmp;
strcpy(tmp->name, name);
memcpy(&tmp->st, st, sizeof(struct stat));
tmp->status = status%2;
}

void show_list(struct list *ls) //遍历打印链表元素  调试的时候使用
{
struct list *p = ls;
while(p) {
p = p->next;
}
}

void del_list(struct list *ls, char *name, struct stat *st) //删除链表中特定的元素
{
struct list *p = ls;
while(p->next) {
if((strcmp(p->next->name, name) == 0) && (p->next->st.st_ino == st->st_ino))
break;
p = p->next;
}
struct list *tmp = p->next;

if(p->next->next == NULL)
p->next = NULL;
else
p->next  = p->next->next;
free(tmp);
}

void free_list(struct list *ls) //释放链表
{
struct list *p = ls->next;
while(p) {
struct list *tmp = p->next;
free(p);
p = tmp;
}
ls->next = NULL;
}

void list_sort(struct list *ls) //链表排序,用过文件的inode号排序,本打算使用别的查找方法,但最终没有实现,暂且放着
{
struct list *i = ls->next;
struct list *j = ls->next;
struct list *tmp = creat_list();

while(i->next) {
while(j->next) {
if(j->st.st_ino > j->next->st.st_ino) {
strcpy(tmp->name, j->name);
strcpy(j->name, j->next->name);
strcpy(j->next->name, tmp->name);

memcpy(&tmp->st, &j->st, sizeof(struct stat));
memcpy(&j->st, &j->next->st, sizeof(struct stat));
memcpy(&j->next->st, &tmp->st, sizeof(struct stat));

tmp->status = j->status;
j->status = j->next->status;
j->next->status = tmp->status;
}

j = j->next;
}
j = ls->next;
i = i->next;
}
free(tmp);
}


function函数文件

#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <errno.h>
#include "defend.h"

#define MAX_PATH 1024

extern struct list *tmp;    //引用外部变量,用于加载链表
extern int status;  //引用外部变量,用于修改文件存在状态

void sys_err(const char *str)
{
perror(str);
exit(0);
}

void load_list(char *dir)   //把文件信息加载到链表中去
{
struct stat st;

if(stat(dir,&st) < 0)
sys_err("stat");

if((st.st_mode & S_IFMT) == S_IFDIR)
read_file(dir);

add_list(tmp, dir, &st);    //加载
}

void read_file(char *file)  //遍历目录中的文件
{
char name[MAX_PATH];
struct dirent *read;
DIR *dir;

if((dir = opendir(file)) < 0)
sys_err("opendir");

while((read = readdir(dir)) != NULL) {
if(strcmp(read->d_name,".") == 0 || strcmp(read->d_name, "..") == 0)
continue;
if(strlen(file) + strlen(read->d_name) + 2 > sizeof(name))
continue;
else {
sprintf(name, "%s/%s", file, read->d_name);
load_list(name);
closedir(dir);
}

void contrast(struct list *ls1, struct list *ls2) //对比两个链表元素,如果第二个链表中有,但第一个链表没有的,就增加到第一个链表,并写log
{
struct list *first = ls1->next;
struct list *second = ls2->next;

while (second) {
if(binary(first, second) != 0) {
add_list(first, second->name, &second->st);
write_log(second, "create");
}
second = second->next;
}
}

int  binary(struct list *ls1, const struct list *ls2) //查找链表中有没有这个元素,有就返回0,并更改第一个链表中的status位,没有就返回-1
{
struct list *first = ls1;

while(first) {
if(ls2->st.st_ino == first->st.st_ino) {
first->status = status%2;
return 0;
}
}
first = first->next;
}

return -1;
}

void check_del(struct list *ls) //检查第一个链表中的status这个字段,来判断文件是否已删除
{
struct list *p = ls->next;
while(p->next) {
if(p->status != status%2) {
printf("inode = %d, status = %d, name = %s, size = %d\n", (int)p->st.st_ino, p->status,  p->name, (int)p->st.st_size);
write_log(p, "delete");
del_list(ls, p->name, &p->st);
}
p = p->next;
}
}

void write_log(struct list *ls, char *buff)  //写日志
{
int fd;
time_t t;
char str[1024] = {0};

fd = open("/home/itcast/filechangelog", O_CREAT|O_RDWR|O_APPEND, 0664);
time(&t);
sprintf(str, "%s\t%s\t%s", buff, ls->name, ctime(&t));
write(fd, str, strlen(str));
close(fd);
}


头文件

#define __DEFEND__

struct list {
char name[256]; //文件名
int status; //删除状态位
struct stat st;     //文件信息
struct list *next;
};

struct list *creat_list();  //创建

void add_list(struct list *, char *, struct stat *); //添加

void show_list(struct list *); //遍历打印

void del_list(struct list *, char *, struct stat *); //删除元素

void free_list(struct list *); //释放链表

void list_sort(struct list *);  //链表排序

void sys_err(const char *);

void load_list(char *);     //加载目录

void read_file(char *);     //遍历目录

void contrast(struct list *, struct list *);    //对比两个链表

int  binary(struct list *, const struct list *);    //查找链表中时候存在某个元素

void check_del(struct list *);  //删除文件不存在的元素

void write_log(struct list *ls, char *buff);    //写日志

#endif


问题:

链表中第一个元素为空,只能判断增加或者删除,顺序查找法,效率低下,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: