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)即可

你可能感兴趣的:(struct,list,File,user,System,终端)