dup系统调用的具体实现祥解

int dup(int oldfd)
主要涉及到3张表的操作:进程打开文件表、系统打开文件表和内存索引节点表。
首先,进程打开文件表是进程U区的一部分,U区的结构如下:
struct    user {
struct    pcb u_pcb;
struct    proc *u_procp;        /* pointer to proc structure */
int    *u_ar0;            /* address of users saved R0 */
char    u_comm[MAXNAMLEN + 1];

/* syscall parameters, results and catches */
int    u_arg[8];        /* arguments to current system call */
int    *u_ap;            /* pointer to arglist */
label_t    u_qsave;        /* for non-local gotos on interrupts */
char    u_error;        /* return error code */
union {                /* syscall return values */
struct    {
int    R_val1;
int    R_val2;
} u_rv;
#define    r_val1    u_rv.R_val1
#define    r_val2    u_rv.R_val2
off_t    r_off;
time_t    r_time;
} u_r;
char    u_eosys;        /* special action on end of syscall */

/* 1.1 - processes and protection */
short    u_uid;            /* effective user id */
short    u_gid;            /* effective group id */
int    u_groups[NGROUPS];    /* groups, 0 terminated */
short    u_ruid;            /* real user id */
short    u_rgid;            /* real group id */

/* 1.2 - memory management */
size_t    u_tsize;        /* text size (clicks) */
size_t    u_dsize;        /* data size (clicks) */
size_t    u_ssize;        /* stack size (clicks) */
struct    dmap u_dmap;        /* disk map for data segment */
struct    dmap u_smap;        /* disk map for stack segment */
struct    dmap u_cdmap, u_csmap;    /* shadows of u_dmap, u_smap, for
   use of parent during fork */
label_t u_ssave;        /* label variable for swapping */
size_t    u_odsize, u_ossize;    /* for (clumsy) expansion swaps */
time_t    u_outime;        /* user time at last sample */

/* 1.3 - signal management */
int    (*u_signal[NSIG])();    /* disposition of signals */
int    u_sigmask[NSIG];    /* signals to be blocked */
int    u_sigonstack;        /* signals to take on sigstack */
int    u_oldmask;        /* saved mask from before sigpause */
int    u_code;            /* ``code'' to trap */
struct    sigstack u_sigstack;    /* sp & on stack state variable */
#define    u_onstack    u_sigstack.ss_onstack
#define    u_sigsp        u_sigstack.ss_sp

/* 1.4 - descriptor management */
struct    file *u_ofile[NOFILE];    /* file structures for open files */
char    u_pofile[NOFILE];    /* per-process flags of open files */
#define    UF_EXCLOSE     0x1        /* auto-close on exec */
#define    UF_MAPPED     0x2        /* mapped from device */
struct    inode *u_cdir;        /* current directory */
struct    inode *u_rdir;        /* root directory of current process */
struct    tty *u_ttyp;        /* controlling tty pointer */
dev_t    u_ttyd;            /* controlling tty dev */
short    u_cmask;        /* mask for file creation */

/* 1.5 - timing and statistics */
struct    rusage u_ru;        /* stats for this proc */
struct    rusage u_cru;        /* sum of stats for reaped children */
struct    itimerval u_timer[3];
int    u_XXX[3];
time_t    u_start;
short    u_acflag;

/* 1.6 - resource controls */
struct    rlimit u_rlimit[RLIM_NLIMITS];
struct    quota *u_quota;        /* user's quota structure */
int    u_qflags;        /* per process quota flags */

/* BEGIN TRASH */
char    u_segflg;        /* 0:user D; 1:system; 2:user I */
caddr_t    u_base;            /* base address for IO */
unsigned int u_count;        /* bytes remaining for IO */
off_t    u_offset;        /* offset in file for IO */
union {
   struct {            /* header of executable file */
int    Ux_mag;        /* magic number */
unsigned Ux_tsize;    /* text size */
unsigned Ux_dsize;    /* data size */
unsigned Ux_bsize;    /* bss size */
unsigned Ux_ssize;    /* symbol table size */
unsigned Ux_entloc;    /* entry location */
unsigned Ux_unused;
unsigned Ux_relflg;
   } Ux_A;
   char ux_shell[SHSIZE];    /* #! and name of interpreter */
} u_exdata;

进程打开文件表的结构如下:
/*
 * Descriptor table entry.
 * One for each kernel object.
 */
struct    file {
    int    f_flag;        /* see below */
    short    f_type;        /* descriptor type */
    short    f_count;    /* reference count */
    short    f_msgcount;    /* references from message queue */
    struct    fileops {
        int    (*fo_rw)();
        int    (*fo_ioctl)();
        int    (*fo_select)();
        int    (*fo_close)();
    } *f_ops;
     caddr_t    f_data;        /* inode 类似于 struct inode *f_uinode;参考: svr2*/
    off_t    f_offset;
};
extern struct file file[];        /*The file table itself 参考: svr2*/

内存索引节点表结构如下:
struct inode {
    struct    inode *i_chain[2];    /* must be first */
    u_short    i_flag;
    u_short    i_count;    /* reference count */
    dev_t    i_dev;        /* device where inode resides */
    u_short    i_shlockc;    /* count of shared locks on inode */
    u_short    i_exlockc;    /* count of exclusive locks on inode */
    ino_t    i_number;    /* i number, 1-to-1 with device address */
    struct    fs *i_fs;    /* file sys associated with this inode */
    struct    dquot *i_dquot;    /* quota structure controlling this file */
    union {
        daddr_t    if_lastr;    /* last read (read-ahead) */
        struct    socket *is_socket;
        struct    {
            struct inode  *if_freef;    /* free list forward */
            struct inode **if_freeb;    /* free list back */
        } i_fr;
    } i_un;
    struct     icommon
    {
        u_short    ic_mode;    /*  0: mode and type of file */
        short    ic_nlink;    /*  2: number of links to file */
        short    ic_uid;        /*  4: owner's user id */
        short    ic_gid;        /*  6: owner's group id */
        quad    ic_size;    /*  8: number of bytes in file */
        time_t    ic_atime;    /* 16: time last accessed */
        long    ic_atspare;
        time_t    ic_mtime;    /* 24: time last modified */
        long    ic_mtspare;
        time_t    ic_ctime;    /* 32: last time inode changed */
        long    ic_ctspare;
        daddr_t    ic_db[NDADDR];    /* 40: disk block addresses */
        daddr_t    ic_ib[NIADDR];    /* 88: indirect blocks */
        long    ic_flags;    /* 100: status, currently unused */
        long    ic_blocks;    /* 104: blocks actually held */
        long    ic_spare[5];    /* 108: reserved, currently unused */
    } i_ic;
};
extern struct inode inode[];/*The inode table itself 参考: svr2*/

最后我们看dup的代码:
dup()
{
    register struct a {
        int    i;
    } *uap = (struct a *) u.u_ap;/*存储参数地方*/
    struct file *fp;
    int j;

    if (uap->i &~ 077) { uap->i &= 077; dup2(); return; }    /* XXX */

    fp = getf(uap->i);/*得到该文件描述所指向的系统活动文件表项*/
    if (fp == 0)
        return;
    j = ufalloc(0);/*找到进程打开文件表中最小的空闲项*/
    if (j < 0)
        return;
    dupit(j, fp, u.u_pofile[uap->i]);/*使找到空闲项指向指定的文件表项*/
}
/
/*
 * Convert a user supplied file descriptor into a pointer
 * to a file structure.  Only task is to check range of the descriptor.
 * Critical paths should use the GETF macro.
 */
struct file *
getf(f)
    register int f;
{
    register struct file *fp;

    if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) {
        u.u_error = EBADF;
        return (NULL);
    }
    return (fp);
}

/*
 * Allocate a user file descriptor.
 */
ufalloc(i)
    register int i;
{

    for (; i < NOFILE; i++)
        if (u.u_ofile[i] == NULL) {
            u.u_r.r_val1 = i;
            u.u_pofile[i] = 0;
            return (i);
        }
    u.u_error = EMFILE;
    return (-1);
}
/
dupit(fd, fp, flags)
    int fd;
    register struct file *fp;
    register int flags;
{

    u.u_ofile[fd] = fp;
    u.u_pofile[fd] = flags;
    fp->f_count++;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值