UNIX System Overview

Unix Architecture

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来打断进程的执行。
另外一个产生信号的方法是调用killfunction。我们可以调用这个函数来发送信号给另一个进程。

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

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猎羽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值