inode,“hard link”和“symbol link”

*nix文件系统上,每个文件的存储实际可以看成包含两部分:inode和实际存储文件内容的数据块。其中inode存储文件的metadata,包含创建时间,访问权限,等等,当然还有指向文件具体数据块的指针。正是通过这个指针,将indoe和数据块关联起来。

要注意,inode中并不保存文件的名字。关于文件名字和inode的映射存储在目录文件中。因此,当访问一个文件时,其实是通过这个文件所在的目录文件访问到这个文件的inode信息,继而进行文件操作的。

接下来,看一下hard linksymbol linkinode之间的关系。首先创建一个文件和指向这个文件的hard linksymbol link

# echo 'Hello, World!' > myfile.txt
# ln myfile.txt my-hard-link
# ln -s myfile.txt my-soft-link

查看这3个文件的inode信息:

# ls -ailt my*
325332 lrwxr-xr-x  1 root  wheel  10 Oct 24 05:26 my-soft-link -> myfile.txt
325331 -rw-r--r--  2 root  wheel  14 Oct 24 05:25 my-hard-link
325331 -rw-r--r--  2 root  wheel  14 Oct 24 05:25 myfile.txt

可以看到myfile.txtmy-hard-link其实对应的的是同一个inode节点:325331,而my-soft-link对应的是另一个inode节点:325332。接下来删除myfile.txt,然后分别读取my-hard-linkmy-soft-link文件内容:

# rm myfile.txt
# ls -ailt my*
325332 lrwxr-xr-x  1 root  wheel  10 Oct 24 05:26 my-soft-link -> myfile.txt
325331 -rw-r--r--  1 root  wheel  14 Oct 24 05:25 my-hard-link
# cat my-hard-link
Hello, World!
# cat my-soft-link
cat: my-soft-link: No such file or directory

可以看到,因为my-hard-linkmyfile.txt对应相同的inode节点:325331,因此删除myfile.txt后,仍然可以通过my-hard-link读取325331这个inode节点所对应的文件内容。而my-soft-link仅仅是指向myfile.txt这个文件名字,因此一旦myfile.txt被删除,也就无法读取文件内容了。

参考资料:
Inodes – an Introduction
What is the difference between a symbolic link and a hard link?

进程的priority和nice

本文选自Difference between nice value and priority in the top output,以Linux系统为例讲解进程的prioritynice
(1)

The difference is that PR is a real priority of a process at the moment inside of the kernel and NI is just a hint for the kernel what the priority the process should have.

Priority反映当时进程真正的优先级,而nice则是告诉kernel进程应该获得什么样的优先级。

(2)Nice的值从-2019-20表示优先级最高。通常情况下,priority = nice + 20,也就是priority的值为0~39。但是上述理论仅仅适用于调度策略是SHED_OTHER的进程,此外,kernel也有可能只改变priority的值,而nice的值保持不变,因此上述等式同样不适用。

Unix中的zombie进程和orphan进程

Unix中子进程退出后,如果父进程没有使用wait()函数获得子进程的退出状态,则子进程的相关信息仍然会在系统的进程表里占用一席之地,这时的子进程称之为zombie进程。如果父进程先于子进程退出,这时的子进程称之为orphan进程,而init进程则会变成orphan进程的父进程。init进程会定期处理父进程是initzombie进程。

参考资料:
Zombie process
Zombie process vs Orphan process

Linux系统中locale相关的笔记

 下列笔记摘自The Linux programming interface

(1)

The actual locales that are defined on a system can vary. SUSv3 doesn’t make any requirements about this, except that a standard locale called POSIX (and synonymously, C, a name that exists for historical reasons) must be defined. This locale mirrors the historical behavior of UNIX systems. Thus, it is based on an ASCII character set, and uses English for names of days and months, and for yes/no responses. The monetary and numeric components of this locale are undefined.

The locale command displays information about the current locale environment (within the shell). The command locale –a lists the full set of locales defined on the system.

(2)

There are two different methods of setting the locale using setlocale(). The locale argument may be a string specifying one of the locales defined on the system (i.e., the name of one of the subdirectories under /usr/lib/locale), such as de_DE or en_US. Alternatively, locale may be specified as an empty string, meaning that locale settings should be taken from environment variables:

setlocale(LC_ALL, “”);

We must make this call in order for a program to be cognizant of the locale environment variables. If the call is omitted, these environment variables will have no effect on the program.

以下摘自stackoverflow.com

A C program inherits its locale environment variables when it starts up. This happens automatically. However, these variables do not automatically control the locale used by the library functions, because ISO C says that all programs start by default in the standard ‘C’ locale.

FreeBSD中的sysctl函数

FreeBSDsysctl家族的函数定义:

#include <sys/types.h>
 #include <sys/sysctl.h>

 int
 sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp,
 const void *newp, size_t newlen);

 int
 sysctlbyname(const char *name, void *oldp, size_t *oldlenp,
 const void *newp, size_t newlen);

 int
 sysctlnametomib(const char *name, int *mibp, size_t *sizep);

sysctl函数参数中,namenamelen用来表明内核参数IDoldpoldlenp用来存储当前内核参数的值;而newpnewlen则用来设置新的内核参数值。如果不需要的话,可以把相应的值置成NULL
看一下sysctlbyname的实现:

int
sysctlbyname(const char *name, void *oldp, size_t *oldlenp,
    const void *newp, size_t newlen)
{
    int real_oid[CTL_MAXNAME+2];
    size_t oidlen;

    oidlen = sizeof(real_oid) / sizeof(int);
    if (sysctlnametomib(name, real_oid, &oidlen) < 0)
        return (-1);
    return (sysctl(real_oid, oidlen, oldp, oldlenp, newp, newlen));
}

可以看到,sysctlbyname首先通过sysctlnametomib获得真正的ID,接着调用sysctl完成想要的工作。

参考资料:
SYSCTL(3)
Grokking SYSCTL and the Art of Smashing Kernel Variables

Sed基础知识

以下内容摘自sed-awk-101-hacks-ebook
Sed语法:

sed [options] {sed-commands} {input-file}
或
sed [options] -f {sed-commands-in-a-file} {input-file}

Sed命令执行流程: 读取一行到一个临时缓存区,然后对这个缓存区执行相应的命令,并输出缓存区的内容,接下来清空缓存区,读取下一行。

Capture

Sed不会修改原始文件,并且总是输出到stdout,因此通常要使用-n选项来禁止自动输出默认的pattern space。举例如下:

# cat employee.txt
101,John Doe,CEO
102,Jason Smith,IT Manager
103,Raj Reddy,Sysadmin
104,Anand Ram,Developer
105,Jane Miller,Sales Manager
# sed '2 p' employee.txt
101,John Doe,CEO
102,Jason Smith,IT Manager
102,Jason Smith,IT Manager
103,Raj Reddy,Sysadmin
104,Anand Ram,Developer
105,Jane Miller,Sales Manager
# sed -n '2 p' employee.txt
102,Jason Smith,IT Manager

如果想保存sed命令的输出,可以把这些输出重定向到某个文件:>filename

 

uptime命令简介

uptime命令用来显示系统已经运行的时间:

# uptime
 19:05:33 up  3:16,  2 users,  load average: 0.00, 0.01, 0.05

19:05:33是当前系统时间,up 3:16是系统已经运行了3小时16分。后面还有用户和系统load信息。如果只关心系统运行了多次时间,可以使用下列命令:

# uptime -p
up 3 hours, 16 minutes

uptime命令得到系统运行时间是通过读取/proc/uptime文件:

# cat /proc/uptime
11984.78 95454.77

第一个字段是系统启动的秒数,第二个字段是系统每个CPU core处在idle状态的时间总和。

 

devfs,tmpfs和devtmpfs

以下摘自Specfs, Devfs, Tmpfs, and Others

specfs – specfs, or Special FileSystem, is a virtual filesystem used to access special device files. This filesystem is odd compared to other filesystems in general because this filesystem does not require a mount-point, yet the OS can still use specfs. However, specfs can be mounted by the user (mount -t specfs none /dev/streams). The device files for character devices in the /dev/ directory use specfs.

devfs – devfs is a device manager in the form of a filesystem. The Device FileSystem is largely the same as specfs except for some differences in the way they function and their uses. devfs is used for most of the device files in /dev/. Most Unix and Unix-like systems use devfs including Mac OS X, *BSD, and Solaris. Nearly all Unix and Unix-like systems that use devfs place it on the kernelspace. However, Linux uses a userspace-kernelspace hybrid approach. This means the devfs virtual filesystem is on the kernelspace and userspace.

tmpfs – The Temporary filesystem is a virtual filesystem for storing temporary files. This filesystem is really in the memory and/or in the swap space. Obviously, all data on this filesystem are lost when the system is shutdown. The mount point is /tmp/.

devtmpfs – This is an improved devfs. The purpose of devtmpfs is to boost boot-time. devtmpfs is more like tmpfs than devfs. The mount-point is /dev/. devtmpfs only creates device files for currently available hardware on the local system.

总结一下:
devfs是文件系统形式的device managertmpfs存在在内存和swap中,因此只能保存临时文件。devtmpfs是改进的devfs,也是存在内存中,挂载点是/dev/

 

Idle状态的CPU在做什么?

What Does an Idle CPU Do?这篇文章介绍了CPUIdle状态下在干什么,讲解地很清晰。我总结一下:

当操作系统“无事可做”时,就会运行Idle进程。以LinuxIdle进程代码为例:

while (1) {
    while(!need_resched()) {
        cpuidle_idle_call();
    }

    /*
      [Note: Switch to a different task. We will return to this loop when the
      idle task is again selected to run.]
    */
    schedule_preempt_disabled();
}

可以看到只要没有“调度”需求(need_resched),就会执行cpuidle_idle_call函数。而对于Intel处理器而言,保持Idle状态意味着执行hlt指令。