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
问题:
链表中第一个元素为空,只能判断增加或者删除,顺序查找法,效率低下,
相关文章推荐
- 最长回文子串
- Scala深入浅出实战经典-1
- Spark源码阅读笔记之BlockObjectWriter
- Android异步之Asynctask与Handler你所应该知道的一切
- 扩展kmp 模板
- CentOS LNMP环境搭建
- Ubuntu下“超级终端”的使用
- Ubuntu14.04.2无法连接无线网络问题解决方案
- 2015 Multi-University Training Contest 4(hdu 5327 - hdu 5338)
- 【剑指Offer面试题】 九度OJ1524:复杂链表的复制
- 怎么让员工爽起来?小米的创始人都是这么干的!
- HDU-4217(树状数组)
- 一个Netfilter nf_conntrack流表查找的优化-为conntrack增加一个per cpu cache
- http封装
- Oracle 学习之RMAN(十五)恢复实战--TSPITR
- 十步图解CSS的position
- JavaScript 获取当前时间戳的代码
- htmlparser 学习
- 画廊视图Gallery组件学习笔记
- 绘图