《UNIX环境高级编程》---1.UNIX基础知识

UNIX 基础知识

一、UNIX 系统

  1. UNIX内核的接口称之为系统调用。公用函数库构建在系统调用接口之上。应用程序既可以使用公用函数库,也可以使用系统调用。

  2. UNIX shell 是一个特殊的应用程序,它为其他应用程序提供了一个接口。

  3. 路径名由斜线分隔的一个或者多个文件名组成的序列:

    • 以斜线开头的路径名称为绝对路径名
    • 以非斜线开头的路径名称为相对路径名

    文件系统根的名字 / 是一个特殊的绝对路径名。它不包含任何其他的字符。

  4. 查看UNIX系统ls命令的 man帮助手册:man 1 ls或者 man -s1 ls

    • 1表示第一部分。由于很多命令的说明文档过于庞大,因此 UNIX将说明文档划分成九个部分。常用的段有:
      • 1: 可执行程序或者 shell command的说明
      • 2: 系统调用的说明
      • 3: 库函数的说明
      • 4: 特殊文件(通常位于/dev/)的说明
      • 8: 系统管理员命令的说明(通常只有 root可用)
    • ls表示shell command,即待查找的目标

ls的简要实现

#include "apue.h"
#include <dirent.h>
int main(int argc, char *argv[])
{
    DIR *dp;
    struct dirent *dirp;
    if (argc != 2)          //argument 
        err_quit("usage:ls directory_name");
    if ((dp = opendir(argv[1])) == NULL)    //if file not exit
        err_sys("can't open %s",argv[1]);
    while((dirp = readdir(dp)) != NULL)
        printf("%s\n",dirp->d_name);
    closedir(dp);
    exit(0);
}

用法:编译后可执行文件myls‘./myls /dev’必须加文件名

标准输出

例如:ls >file.list,即将ls显示的内容标准输出到文件file.list上。
同理我们编写的程序 : ./myls /dev > file.list

不带缓冲的I/O

mycopy.c

/*
    std output from std input
*/
#include "apue.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)
            err_sys("write error");
    if(n < 0)
        err_sys("read error");
    exit(0);
}

用法:编译后mycopy ,运行./mycopy >data
则表示从终端接收输入,存进data文件中,打开data即是我们从终端出入的内容。ctrl +D,终止输入。
若要将一个文件的内容复制到另一文件,则可使用

./mycopy <data> data1//将data的内容复制到data1中

标准I/O

/*
    std output from std input
*/
#include "apue.h"
int main(void)
{
    int c;

    /*while input enter key,the function read() begin read data(include "\n")*/
    while((c = getc(stdin)) != EOF)  //一次获取一个元素
        if (putc(c,stdout) == EOF)
            err_sys("output error");
    if (ferror(stdin))
        err_sys("input error");

    exit(0);
}
  1. 每个进程都有一个工作目录,有时称他为当前工作目录。所有的相对路径名都是从工作目录开始解释。

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

  2. 登录时, shell的工作目录设置为起始目录

  3. UNIX系统中,每个进程都有一个唯一的数字标志符,称为进程ID(一个非负整数)。

  4. 通常一个进程只有一个线程。但是你也可以创建多个线程。

    • 一个进程内的所有线程共享同一个地址空间、文件描述符、栈、进程相关属性
    • 多线程的程序需要在各线程访问共享数据时采取措施来避免不一致性
    • 线程也用ID标识,但是线程ID只有在它所属的进程内有意义
  5. 用户和组:

    • 用户ID:标识各个不同的用户;用户ID为0的用户为根用户,其登录名为 root,它具有超级用户权限。
    • 组ID:用户所属的组的标识。
    • 附属组ID: 一个用户可以属于多个组,这些组就是附属组。由附属组的ID来标识。

二、错误处理

  1. 当 UNIX 系统函数出错时,通常会返回一个负值,同时整型变量 errno 通常被设置为具有特定信息的值。

    • 文件 <errno.h> 定义了 errno 以及赋予它的各种常量,这些常量以 E字符开头
    • 在多线程环境中,每个线程都有属于自己的局部 errno,以避免一个线程干扰另一个线程。

    对于 errno 的使用要注意两条规则:

    • 如果没有出错,则errno的值不会被清除.因此只有在函数的返回值指明出错了时,检查errno才有意义
    • 任何函数都不会将errno的值清零,且在<errno.h>中定义的所有常量都不为0
  2. strerror/perror函数:用于处理错误信息

    
    #include<string.h>
    
    char *strerror(int errnum);
    
    #include<stdio.h>
    
    void perror(const char*msg);
    • strerror: 将 errnum(通常就是 errno值)映射为一个出错消息字符串,并且返回此字符串的指针
      • 输入: 一个整数(通常是errno的值)
      • 输出: 出错消息字符串的指针(不需要用户手动分配出错消息字符串的内存)
    • perror: 基于 errno的当前值,在标准错误上产生一条出错消息,然后返回。这条出错消息首先是 msg指向的字符串,后面是冒号,后面是一个空格,后面是对应于 errno值的出错消息,最后是一个换行符。
      • 输入:附加的出错消息
      • 输出:无输出。但是向标准错误上输出一条出错消息,这条出错消息如上所述。

    errno handle

  3. 出错恢复:可以将<errno.h>中定义的错误分成两类:

    • 致命性错误:此类错误无法恢复。最多只能在屏幕上打印一条出错消息或者将出错消息写入日志,然后退出。
    • 非致命性错误:此类错误可以妥善处理。大多数非致命性错误时暂时的(比如资源短缺)

    与资源相关的非致命性错误包括:EAGAIN、ENFILE、ENOBUFS、ENOLCK、ENOSPC、EWOULDBLOCK.其典型的处理方法是:延迟一段时间,然后重试。

    • 有时候 ENOMEM 也是非致命性出错
    • EBUSY 指明 共享资源正在使用是,也可视为非致命性出错处理
    • EINTR 中断一个慢速系统调用时,可以视为非致命性出错处理

三、时间

  1. UNIX 系统使用两种时间:

    • 日历时间:自 UTC 1970年1月1日 00:00:00 以来经历过的秒数累计值。用 time_t数据类型来保存这种时间值。
    • 进程时间:也称作CPU时间,用于度量进程使用的CPU资源。进程时间以时间滴答来计算,用clock_t数据类型保存这种时间值。
  2. 当度量一个进程的执行时间时,UNIX系统为一个进程维护了3个进程时间值:

    • 时钟时间: 又称作墙上时钟时间,是进程运行的时间总量,其值与系统中同时运行的进程数有关
    • 用户CPU时间:执行用户指令所用的时间量
    • 系统CPU时间:该进程执行内核程序所经历的时间。如进程执行一个read系统调用,则内核执行该系统调用的时间计入系统 CPU 时间

    用户CPU时间和系统CPU时间之和称作 CPU 时间

  3. 运行 shell 命令 time 可以获取进程的时钟时间、用户时间和系统时间。time的参数请参考 man手册

    time_command

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值