【问题标题】:Kernel Panic after changes in sys_closesys_close 更改后的内核恐慌
【发布时间】:2010-12-16 01:24:43
【问题描述】:

我正在学习操作系统课程,我们使用 Linux Red Hat 8.0 作为作业的一部分,我不得不更改 sys close 和 sys open。对 sys close 的更改顺利通过,但是当我突然引入对 sys close 的更改时,操作系统在启动过程中遇到错误,声称它无法挂载 root fs,并引发恐慌。据报道,当这种情况发生时,EIP 处于系统关闭状态。

以下是我所做的更改(查找“HW1 添加”评论): 在 fs/open.c 中:

asmlinkage long sys_open(const char * filename, int flags, int mode)
{
    char * tmp;
    int fd, error;
    event_t* new_event;

#if BITS_PER_LONG != 32
    flags |= O_LARGEFILE;
#endif
    tmp = getname(filename);
    fd = PTR_ERR(tmp);
    if (!IS_ERR(tmp)) {
        fd = get_unused_fd();
        if (fd >= 0) {
            struct file *f = filp_open(tmp, flags, mode);
            error = PTR_ERR(f);
            if (IS_ERR(f))
                goto out_error;
            fd_install(fd, f);
        }
        /* HW1 additions */
        if (current->record_flag==1){
            new_event=(event_t*)kmalloc(sizeof(event_t), GFP_KERNEL);
            if (!new_event){
                new_event->type=Open;
                strcpy(new_event->filename, tmp);
                file_queue_add(*new_event, current->queue);
            }
        }
        /* End HW1 additions */
out:
        putname(tmp);
    }
    return fd;

out_error:
    put_unused_fd(fd);
    fd = error;
    goto out;
}

asmlinkage long sys_close(unsigned int fd)
{
    struct file * filp;
    struct files_struct *files = current->files;
    event_t* new_event;
    char* tmp = files->fd[fd]->f_dentry->d_name.name;   

    write_lock(&files->file_lock);
    if (fd >= files->max_fds)
        goto out_unlock;
    filp = files->fd[fd];
    if (!filp)
        goto out_unlock;
    files->fd[fd] = NULL;
    FD_CLR(fd, files->close_on_exec);
    __put_unused_fd(files, fd);
    write_unlock(&files->file_lock);
    /* HW1 additions */    
    if(current->record_flag == 1){
        new_event=(event_t*)kmalloc(sizeof(event_t), GFP_KERNEL);
        if (!new_event){
            new_event->type=Close;
            strcpy(new_event->filename, tmp);
            file_queue_add(*new_event, current->queue);
        }
    }
    /* End HW1 additions */
    return filp_close(filp, files);

out_unlock:
    write_unlock(&files->file_lock);
    return -EBADF;
}

在 schedule.h 中定义的 task_struct 在最后被更改为包括:

unsigned int record_flag; /* when zero: do not record. when one: record. */
file_queue* queue;

并且文件队列和事件t在一个单独的文件中定义如下:

typedef enum {Open, Close} EventType;

typedef struct event_t{
    EventType type;
    char filename[256];
}event_t;

typedef struct file_quque_t{
    event_t queue[101];
    int head, tail; 
}file_queue;

文件队列添加的工作方式如下:

void file_queue_add(event_t event, file_queue* queue){ 
    queue->queue[queue->head]=event;
    queue->head = (queue->head+1) % 101;
    if (queue->head==queue->tail){
        queue->tail=(queue->tail+1) % 101;
    }
}

【问题讨论】:

  • 你能把系统崩溃时得到的堆栈转储放在一边吗?

标签: linux linux-kernel panic


【解决方案1】:
if (!new_event) {
    new_event->type = …

相当于if (new_event == NULL)。我想你的意思是if (new_event != NULL),内核人员通常写成if (new_event)

【讨论】:

  • 你是对的,但这并不能解决问题。真正让我感到困惑的是,由于所有进程都被创建为将 record_flag 设置为 0,因此此代码部分甚至不应该有效果,而问题只有在我引入这些更改后才会出现。
【解决方案2】:

能否请您发布错误的堆栈转储。我没有看到为 queue_info 结构分配内存的地方。还有一件事是,如果内核中未分配进程 record_flag,您无法确定该进程是否始终为零,因为内核是一个长时间运行的程序,并且内存包含垃圾。

还可以通过查看堆栈跟踪来检查函数中发生的确切位置。

【讨论】:

    猜你喜欢
    • 2013-12-12
    • 1970-01-01
    • 2020-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 2015-12-11
    • 2023-03-26
    相关资源
    最近更新 更多