Unix 基础知识

APUE 第一章 Unix 基础知识总结


1. Unix 体系结构 

APUE第一章给出了Unix操作系统的系统结构(如下图),非常形象的说明了从程序运行角度来看Unix 系统的分层结构:



最里面最核心的是操作系统内核(kernel),内核的接口即为系统调用(system call). shell 是一个命令行解释器(命令行解释程序),它读取用户输入,然后执行命令。。用户程序(application)可以在Shell上运行,可以调用Library运行,也可以直接调用system calls 运行。 


从程序运行的角度来看,kernel 是OS 这个程序本身,主要是驱动和管理硬件,同时为上层应用提供调用系统资源的能力;

system calls 就是系统接口, 和windows编程中WIN32 API 本质上是同一类东西

shell 是一个命令行解释程序,基于system calls 

library routines 是对system calls 的又一层封装

Application 可以直接调用系统接口(system calls) ,也可以调用封装程度较高的library routines, 也可以调用shell 命令(shell 脚本) 来与kernel 交互,本质上都是调用kernel 开发的接口。



2.  登录

登录到Unix 系统会校验用户名和密码

系统在口令文件 /etc/passwd 中查看登录名,  典型的口令文件内容如下:




口令文件中的登录项由7个以冒号分隔的字段组成,依次是:

登录名,加密口令,用户ID,组ID,注释字段,起始目录以及shell 程序

root:x:0:0:root:/root:/bin/bash

该项表示 root 用户, 加密口令用x 表示,  用户ID为0, 组ID为0, 注释字段为root , 起始目录为/root ,对应的shell 程序为/bin/bash


3.  shell

shell 是一个命令行解释器

Linux 上一般会支持Bourne shell(/bin/sh) 和Bourne-again shell(/bin/bash) , 一般默认使用bash, Max OS X 的默认shell也是 bash



4. 文件和目录

Unix文件系统是目录和文件的一种层次结构,所有东西的起点是根(root)目录, 用斜杠"/"来表示


目录的逻辑视图与实际在磁盘上的不同,  详细可以了解下Linux 系统的挂载操作


POSIX.1 推荐将文件名限制在以下字符集之内:字母(a~z,A~Z),数字(0~9),句点(.),短横线(-)和下划线(_)

创建目录是会自动创建两个文件名:  .  (点)和 ..(点点),点指向当前目录,点点指向父目录。  在最高层级的目录中,点与点点相同


路径名包含绝对路径和相对路径


工作目录: 每个进程都有一个工作目录(working directory),有时称为当前工作目录(current working directory)  ,所有相对路径从工作目录开始解释

进程可以用chdir 函数来更改其工作目录


起始目录:

登录时,工作目录设置为起始目录;  起始目录在口令文件/etc/passwd 中指定。


自己实现ls 命令(ls 命令接受目录为输入,列出该目录下所有的文件和目录)

#include "apue.h"
#include <dirent.h>

int main(int argc ,char* argv[])
{
        DIR *dp;
        struct dirent *dirp;
        if(argc != 2)
                printf("usage: ls directory_name");

        if( (dp = opendir(argv[1]) ) == NULL   )
                printf("can't open %s",argv[1]);
        while ( (dirp = readdir(dp) ) != NULL )
                printf("%s\n",dirp->d_name);

        closedir(dp);
        exit(0);
}


PS.  Linux 或Unix 系统编程可能还是C语言适合(C 比C++在Unix 系统编程方面还是有优势的),因为POSIX 标准是包含ISO C标准的, 系统本身是C语言的,system call 的接口也是C语言的




5.  输入和输出

文件描述符(file descriptor ) 通常是一个非常小的非负整数,内核用以表示一个特定的进程正在访问的文件。当内核打开一个现有文件或创建一个新文件时,它都返回一个文件描述符。

每当运行一个新程序时,所有shell 都为其打开3个文件描述符,即标准输入(standard input), 标准输出(standard output) 以及标准错误(standard error).  默认情况下,这3个文件描述符都指向终端。  大多数shell 提供一种方法,是其中的描述符可以重定向到文件



6 程序和进程

程序时一个存储在磁盘上某个目录中的可执行文件。内核使用exec函数(7个exec 函数之一) 将程序读入内存,并执行程序。

程序的执行实例被称为进程(process)

Unix 系统确保每个进程都有一个唯一的数字标识符,称为进程ID(process ID),进程ID总是一个非负整数


进程控制的3个主要函数:fork,exec 和waitpid


通常一个进程只有一个控制线程(thread)---某一时刻执行的一组机器指令

一个进程内的所有线程共享同一地址空间,文件描述符,栈及进程相关属性

线程ID只在所属的进程中有意义



7.出错处理

当Unix系统函数出错时,通常会返回一个负值

<errno.h> 定义了errno 以及可以赋予它的各种常量, UNIX中intro(2) 手册中列出了这些出错常量,Linux 系统中errno(3) 手册页列出了这些常量


C标准定义了两个函数,用于打印出错信息:

char * strerror(int errnum)   //将errno 映射为一个出错消息字符串

void perror(const char * msg) 打印出错消息


8 用户ID

用户ID在口令文件 /etc/passwd 中映射

组文件将组名映射为组ID,组文件通常是/etc/group

对于系统来说,使用数字的用户ID和组ID设置权限和校验权限方便,对于用户来说使用名字方便

可以使用系统函数getuid() 和getgid() 来获取用户ID和组ID

大多数Unix系统允许一个用户属于多个组,4.2BSD允许一个用户属于多至16个组,POSIX 要求系统至少应该支持8个附属组。


9. 信号(signal)

signal 用户通知进程发生了某种情况

进程对于信号有3种处理方式:忽略信号,系统默认方式处理(通常是终止进程),提供一个信号处理函数

信号产生的情况:  键盘上的中断键(Delete 或者Ctrl+X)  ,  推出键(Ctrl+\) ,  调用kill 函数

当向一个进程发送信号时,我们必须是该进程的所有者或者超级用户

系统提供signal() 函数来指定对某一类信号的处理函数


10 时间

Unix 系统使用两种不同时间

日历时间:  UTC 1970年1月1日 00:00:00 以来所经过的秒数累计值,系统基本数据类型time_t 用于保存这种时间

进程时间,也称CPU 时间,clock_t 类型保存这种时间值,进程时间以时钟滴答计算

Unix系统为一个进程维护了3个进程时间值:  

时钟时间:进程运行的时间总量,与系统中同时运行的进程数量有关

用户CPU时间:执行用户指令所用的时间量

系统CPU: 为该进程执行内核程序所经历的时间

time(1) 命令可以获得进程的时间


11.系统调用与库函数

Linux 3.2.0 提供了380个系统调用(system call) ,FreeBSD 8.0 提供了450以上系统调用

Unix 系统使用的技术是:  为每个系统调用在标准C库中设置一个具有相同名字的函数,用户程序使用标准C调用序列来调用这些函数,然后这些函数又调用系统所要求的技术调用相应的内核服务。 从应用角度来看,可以将系统调用视为C函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值