天天看点

coreutils-5.0中几个命令的执行过程

uname是怎么执行的?

随手在键盘敲击一个uname -a,系统信息就出来了:

Linux My 2.6.8-2-686-smp #1 SMP Tue Aug 16 12:08:30 UTC 2005 i686 unknown unknown GNU/Linux

可是执行该命令时,系统究竟做了什么?如果查阅coreutils的uname.c文件就会发现其实uname使用了一个系统调用sys_uname:

asmlinkage int sys_uname(struct old_utsname __user * name)

{   

    ...

    err=copy_to_user(name, &system_utsname, sizeof (*name));

}

name作为传出参数接受内核的返回,可见系统通过保存一个静态的变量system_utsname来支援uname系统调用,我们看一下最重要的结构体:

struct utsname {

    char sysname[];

    char nodename[];

    char release[];

    char version[];

    char machine[];

#ifdef _GNU_SOURCE

    char domainname[];

#endif

};

从每个字段的名字可以看出uname支持的选项,-s,-n,-r,-v,-m,-a(--all),从上面uname -a的输出也可以看出输出信息分为5个段。最后看一下系统保留的那个静态结构体,作为系统调用uname的结果:

struct new_utsname system_utsname = {

    .sysname    = UTS_SYSNAME,

    .nodename    = UTS_NODENAME,  /* set by sethostname() */

    .release    = UTS_RELEASE,

    .version    = UTS_VERSION,

    .machine    = UTS_MACHINE,

    .domainname    = UTS_DOMAINNAME, /* set by setdomainname() */

who/users等命令是怎么执行的?

who/users命令使用了一个文件,在我的系统上,它的全路径是:/var/run/utmp,该文件中保存了一个下列结构体的数组:

struct utmp {

    ...          

这个文件既然保存了一个结构体数组,因此也就不要指望可以将该文件作为文本文件来读取了,虽然它也不是可以要做成二进制的。如果想解析该文件,那么必须逐数组元素逐字段地解析,下面的函数是解析流程:

int read_utmp (const char *filename, int *n_entries, STRUCT_UTMP **utmp_buf)

{

    FILE *utmp;

    struct stat file_stats;

    size_t n_read;

    size_t size;

    STRUCT_UTMP *buf;

    utmp = fopen (filename, "r");

    fstat (fileno (utmp), &file_stats);

    size = file_stats.st_size;

    buf = (STRUCT_UTMP *) xmalloc (size);

    n_read = fread (buf, 1, size, utmp);

    *n_entries = size / sizeof (STRUCT_UTMP);

    *utmp_buf = buf;

    return 0;

命令who的执行过程不外乎就是:

static void who (const char *filename)

    int n_users;

    STRUCT_UTMP *utmp_buf;

    int fail = read_utmp (filename, &n_users, &utmp_buf);

    if (short_list)

        list_entries_who (n_users, utmp_buf); //实现一个循环来读取utmp_buf中的各个元素的ut_name字段

    else

        scan_entries (n_users, utmp_buf); //循环读取每个元素的各个字段

tty命令是怎么执行的?

在任意终端输入tty命令,得到的是诸如/dev/ttyn,/dev/pts/n之类的输出,这是怎么回事?看一下coreutils的tty.c的源代码之后就会发现实际上tty调用了一个叫做ttyname的函数,实际上就是取得标准输入,也就是文件描述符0所对应的设备文件,如下:

KOAL-ECCDEV-01:~/coreutils/coreutils-5.0/src# tty

/dev/pts/0

如果将标准输入重定向到一个普通文件:

KOAL-ECCDEV-01:~/coreutils/coreutils-5.0/src# tty 0>aaa

not a tty

说明ttyname正如man手册描述的那样,会检查终端设备的正确性,如果在/dev/pts/0上执行下面的:

KOAL-ECCDEV-01:~/coreutils/coreutils-5.0/src# tty 0>/proc/25542/fd/0 #25542为pts/1的ping 127.0.0.1

/dev/pts/1

可见输出的是别的终端,其实只要在/dev/pts/n上执行tty 0 > /dev/pts/m(m!=n)即可

 本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1271816

继续阅读