0

ops-classの割り当て 2 に取り組んでいます。

次の関数は、作成中のプロセス (ここで提供されるテスト プログラムのユーザー プロセスなど) のファイル ハンドラー配列をブートストラップします。

int _fh_bootstrap(struct fharray *fhs){

/* Initialize the file handle array of this process */
fharray_init(fhs);

/* String variables initialized for passage to vfs_open */
char* console_inp = kstrdup(CONSOLE); // CONSOLE = "con:"
char* console_out = kstrdup(console_inp);
char* console_err = kstrdup(console_inp);

/* Return variable */
int ret = 0;

/* Initialize the console files STDIN, STDOUT and STDERR */
struct vnode *stdin;
ret = vfs_open(console_inp,O_RDONLY,0,&stdin);
if(ret != 0){
    return ret;
}
kfree(console_inp);

struct fh *stdinfh = kmalloc(sizeof(struct fh));
ret =  _fh_create(O_RDONLY,stdin,stdinfh);
if(ret != 0){
    return ret;
}

stdinfh->fd = STDIN_FILENO;
fharray_add(fhs,stdinfh,NULL);

struct vnode *stdout;
ret = vfs_open(console_out,O_WRONLY,0,&stdout);
if(ret != 0){
    return ret;
}
kfree(console_out);

struct fh *stdoutfh = kmalloc(sizeof(struct fh));
ret =  _fh_create(O_WRONLY,stdout,stdoutfh);
if(ret != 0){
    return ret;
}

stdoutfh->fd = STDOUT_FILENO;
fharray_add(fhs,stdoutfh,NULL);

struct vnode *stderr;
ret = vfs_open(console_err,O_WRONLY,0,&stderr);
if(ret != 0){
    return ret;
}
kfree(console_err);

struct fh *stderrfh = kmalloc(sizeof(struct fh));
ret =  _fh_create(O_WRONLY,stderr,stderrfh);
if(ret != 0){
    return ret;
}

stderrfh->fd = STDERR_FILENO;
fharray_add(fhs,stderrfh,NULL);

fharray_setsize(fhs,MAX_FD);    

return 0;

/* Initialization of stdin, out and err filehandlers complete */
}

os161-gdb を使用してこの関数をステップ実行すると、次のことがわかります。

//*stdinfh after the call to _fh_create 
{fd = 0, flag = 0, fh_seek = 0, fh_vnode = 0x80044ddc}

//**stdinfh->fh_vnode
{vn_refcount = 2, vn_countlock = {splk_lock = 0, splk_holder = 0x0}, vn_fs = 0x0,
vn_data = 0x8004ab60, vn_ops = 0x8003e690 <dev_vnode_ops>}

これが奇妙な部分です。kmalloc への 2 回目の呼び出し (stdoutfh を初期化するため) を実行した後、stdinfh->fh_vnode ポインターの値が変わります!

//**stdinfh->fh_vnode
(struct vnode *) 0x1

さらに奇妙なことに、次の行に進んだ後

fharray_add(fhs,stdoutfh,NULL);

*stdoutfh->fh_vnode と *stdinfh->fh_vnode の値は同じです

1 つの考えられる説明: OS に十分なヒープ メモリがありませんか。ありそうもないと思いますし、これを想定した後でも、ここで何が起こっているのかを正確に説明することはできません.

いくつかの余分なコード

  1. _fh_create
  2. 構造体 fh 定義

    static int _fh_create(int flag, struct vnode *file, struct fh *handle){
    
    KASSERT(file != NULL);
    
    /* W , R , RW */
    if ( 
        ((flag & O_RDONLY) && (flag & O_WRONLY)) ||
        ((flag & O_RDWR) && ((flag & O_RDONLY) || (flag & O_WRONLY)))
    ) {
        handle = NULL;
        return 1;
    }
    
    handle->flag = flag;
    handle->fh_seek = 0;
    handle->fh_vnode = &file;
    
    return 0;
    }
    

    struct fh { uint32_t fd; // file descriptor int flag; // File handler mode off_t fh_seek; // seek position in file struct vnode **fh_vnode; // File object of the file }

struct vnode の定義はここにあります。

さらに情報が必要な場合はお知らせください。ご協力ありがとうございます。

4

1 に答える 1

1

コードhandle->fh_vnodeは自動変数 (「スタック上」) へのポインターを設定しています。関数パラメーターは自動変数です。関数が戻った後、これはダングリング ポインターになります。

これを修正するには、コードを少し再設計する必要があります。たとえば、は へのポインタではなくstruct fh格納する必要があります。filefile

于 2017-01-12T04:45:03.303 に答える