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


题目:编写监控/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

问题:

链表中第一个元素为空,只能判断增加或者删除,顺序查找法,效率低下,
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值