您的位置:首页 > 其它

UNIX System Overview

2016-02-04 11:47 337 查看

Unix Architecture



Logging in

登录unix系统时,我们输入的账户密码需要在密码文件中检查。密码文件中包含了用户名,加密的密码,home目录,shell program(/bin/ksh)等等内容。

有些系统将密码存放到了其他的文件之中。

shells

shell是一种command-line interpreter用于读取用户输入并且执行指令。用户输入命令可以通过terminal也可以通过shell脚本 来输入。

Files and Directories

file system

filename

pathname

Working Directory

每个程序都有一个工作目录。比如doc/memo/joe,就是在工作目录下的doc中的memo目录中的joe目录或者文件。而/usr/lib就是绝对路径,根目录下的usr目录下的Lib目录。

Home Directory

Input and Output

File Descriptors

文件描述符是内核用来标志被特殊进程访问的文件,通常是小的非负整数。文件描述符可以用来完成read和write操作。

Standard input, Standard Output, and Standard Error

无论哪个程序运行的时候,所有的shell会打开三个描述符-对应于标准input/out/error>

当只是简单地运行一个命令的时候,如:

ls


then all three are connected to the terminal.

大部分shell提供重定向的方法,例如:

ls > file.list


就将standard ouput重定向到文件file.list中去。

Unbuffered I/O

无缓冲IO通过函数open,read,write,lseek,and close提供。这些函数都操作file descriptor.

Example

使用一个例子演示复制文件1到第二个文件中,使用了重定向。因为我是用的是ubuntu,与书中的代码进行了一些修改,本人亲自实验过,因此代码都是可用的。

#include <stdio.h>
#include <unistd.h>

#define BUFFSIZE 4096

int main(void)
{
int n;
char buf[BUFFSIZE];

while((n = read(STDIN_FILENO, buf, BUFFSIZE))>0)
{
if(write(STDOUT_FILENO, buf, n) != n)
{
fprintf(stderr, "write error");
}
}
if(n < 0)
{
fprintf(stderr, "read error");
}

return 0;
}


gcc编译成功后执行:

./a.out < infile > outfile


文件infile重定向为a.out的标准输入,outfile重定向为a.out的标准输出。执行该命令后,infile文件内容会复制到outfile中。

Standard I/O

标准IO在unbuffered I/O之上提供了具有缓冲能力的接口。使用标准IO不需要我们考虑选择合适的缓冲区大小,例如上例的BUFFSIZE。此外标准IO简化了对于输入一行一行的处理。例如:
fgets
就直接读取完整的一行。最典型的标准IO函数就是
printf


头文件为
<stdio.h>


接下来对于上一个例子进行改写。

Example

#include <stdio.h>

int main(void)
{
int c;
while((c = getc(stdin)) != EOF)
{
if(putc(c, stdout) == EOF)
{
fprintf(stderr, "out error!");
}
}
if(ferror(stdin))
{
fprintf(stderr, "input error!");

}

return 0;
}


此外解释一下代码中的函数功能:

ferror(stdin)
用于检查流上的错误,如果标准输入流有错,则报错

Programs and Processes

Program

程序是在硬盘上的可执行文件。一个程序被读进内存中并且被内核执行,内核使用six exec functions中的一种来执行程序。具体的内容会在后续章节讲解。

Process and Process ID

进程是程序被执行的过程。一些操作系统使用术语
task
来指代被执行的程序。

Unix系统使用非负整数的进程ID来区别进程。

Process Control

有三种主要函数进行进程控制:

fork
exec(has six variants)
waitpid


Threads and Thread IDs

通常进程仅仅有一个线程-同一时间一组机器指令执行。

在一个进程中所有的线程分享同样的地址空间、文件描述符、stacks、和进程相关的属性。因为共享的特性,所以需要注意线程同步问题。

Error Handling

在UNIX系统函数中产生错误的时候,会返回负数,此外
errno
会被设置为某值—用于提供额外的信息。

此外一些函数发生错误会返回
null
指针。

在头文件
<errno.h>
定义了
errno


如果你想在Linux中查询错误常量列表,你需要在
errno(3) manual page
中查看。

对于errno有两点需要注意:

1. 如果function没有出错,则不会清除errno的值。因此只有在发生错误后查看errno的值才是有意义的。

2. errno永远不会被设置为0

C标准中有2个函数用来帮助打印错误信息:

#include <string.h>

char * strerror(int errnum);


#include <stdio.h>

void perror(const char *msg);


Error Recovery

定义在头文件
<errno.h>
的错误可以被分为两类:致命的和非致命的。只有非致命的(nonfatal)可以被修复。资源相关的非致命错误中,
EBUSY
表示共享的资源正在被使用。
EINTR
表示interrupts a slow system call.

对于资源非致命错误典型的处理办法就是等待一会儿再试一次。

1.8 User Identification

User ID

用于标示用户,ID 0就是
root
的用户ID。

Group ID

用户成组,便于共享资源等。

1.9 Signals

信号是一种通知进程一些环境已经发生了改变的技术。例如,进程除以0,名为
SIGFPE
的信号就会发送给进程。

每个进程有三个选择来处理信号:

1. 忽略信号

2. 执行默认的操作

3. 提供自定义的函数来执行。

很多环境都有信号产生,例如终端使用Ctrl+C来打断进程的执行。

另外一个产生信号的方法是调用
kill
function。我们可以调用这个函数来发送信号给另一个进程。

但是:我们必须是另一个进程的拥有者才可以这样做

1.10 Time Values

UNXI系统拥有两种时间值:

1. 日历时间

2. 进程时间

对于每个进程拥有三种时间值:

1. clock time(wall clock time)进程运行的总时间,该值也取决于系统运行的其他进程。

2. User CPU time,用户指令的CPU时间。

3. System CPU time,内核中运行该进程的时间。

为了测量这些时间,只需要简单的执行
time(1)
命令。例如:

cd /user/include
time -p grep _POSIX_SOURCE */*.h > /dev/null
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: