APUE学习笔记(一)unix基础知识

1.1 Unix体系

内核的接口被称为系统调用。公用函数库构建在系统调用接口之上。shell和公共函数都能直接进行系统调用,
应用程序可以直接进行系统调用,也可以使用shell和公共函数库里的函数,从而间接进行系统调用。

1.2 登录

shell是一个命令行解释器,它读取用户输入然后执行命令。shell的用户输入通常来自于终端(交互式shell),
有时则来自于文件(称为shell脚本)。

1.3 文件和目录

除了斜线(/)和空格之外,都可以用于文件名;由斜线分隔的多个文件名构成路径名。

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

int main(int argc, char *argv[]) {
    DIR *dp;
    struct dirent *dirp;

    if (argc != 2) {
        err_quit("usage: ls directory name");
    }
    if ((dp = opendir(argv[1])) == NULL) {
        err_sys("cannot open %s", argv[1]);
    }
    while ((dirp = readdir(dp)) != NULL) {
        printf("%s\n", dirp->d_name);
    }
    closedir(dp);
    return 0;
}

1.4 输入输出

每当运行一个新程序的时候,所有的shell都会为其打开三个文件描述符,即标准输入、标准输出和标准错误.

函数open、 read、 write、 lseek以及close提供了不带缓冲的I/O。 这些函数都使用文件描述符。

按照字节读取和写入,借助于缓冲区。标准I/O函数为那些不带缓冲的I/O函数提供了一个带缓冲的接口。

#include "apue.h"

int main(void) {
    int c;
    while ((c = getc(stdin)) != EOF) {
        if (putc(c, stdout) == EOF) {
            err_sys("output error");
        }
    }

    if (ferror(stdin))
        err_sys("input error");

    exit(0);
}

1.5 程序和进程

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

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

#include "apue.h"

int main(void) {
    printf("hello world from process with id %d", getpid());

    exit(0);
}

有三个用户进程控制的主要函数:fork、exec和waitpid。

 #include "apue.h"

#define	BUFFSIZE	1024

int main(void)
{
    char	buf[BUFFSIZE];
    pid_t  pid;
    int status;

    printf("%% ");

    while ((fgets(buf, BUFFSIZE, stdin)) != NULL)
    {
        if (buf[strlen(buf) -1] == '\n')
            buf[strlen(buf) -1] = 0;

        if ((pid = fork()) < 0)
            err_sys("fork error");
        else if (pid == 0 ) {
            /*
             * int execlp(const char * file,const char * arg,....);
             * 传入参数可执行文件名,会从PATH路径下去寻找,agr0和file同名,最后一个参数必须是NULL
             */
            execlp(buf, buf, NULL);
            err_ret("exec %s error", buf);
            exit(127);
        }
        //父进程等待子进程退出
        if ((pid = waitpid(pid, &status, 0)) < 0)
            err_sys("wait error");

        printf("%% ");

    }

    exit(0);
}

1.6 出错处理

当UNIX系统函数出错时通常会返回一个负值,而且整型变量errno通常被设置为具有特定信息的值。errno可以是一个整形或是一个函数指针。

对于errno,如果没有出错其值不会被清除。仅当函数的返回值指明出错时才检验其值。任何函数都不会将errno值设置为0,而且在<errno.h>中定义的所有常量都不为0。

致命性错误:无法恢复
非致命错误:通常是临时错误,比如资源问题

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

int main(int argc, char*argv[]) {
    printf("EGAIN: %s\n", strerror(EAGAIN));
    errno = EAGAIN;
    perror(argv[0]);
}

1.7 用户标识

用户ID为0的用户为root用户.

#include "apue.h"

int main(int argc, char*argv[]) {
    printf("getuid: %d, getgid: %d\n", getuid(), getgid());
}

1.8 信号

信号通知进程发生了事件。进程处理信号的方式:

  1. 忽略, 2. 按照系统默认方式, 3.调用预设函数
#include "apue.h"
#include <sys/wait.h>

#define	BUFFSIZE	1024

static void sig_int(int);

int main(void)
{
    char	buf[BUFFSIZE];
    pid_t  pid;
    int status;

    if (signal(SIGINT, sig_int) == SIG_ERR)  //设置SIGINT信号处理函数
        err_sys("signal error");

    printf("%% ");

    while ((fgets(buf, BUFFSIZE, stdin)) != NULL)
    {
        if (buf[strlen(buf) -1] == '\n')
            buf[strlen(buf) -1] = 0;

        if ((pid = fork()) < 0)
            err_sys("fork error");
        else if (pid == 0 ) {
            /*
             * int execlp(const char * file,const char * arg,....);
             * 传入参数可执行文件名,会从PATH路径下去寻找,agr0和file同名,最后一个参数必须是NULL
             */
            execlp(buf, buf, NULL);
            err_ret("exec %s error", buf);
            exit(127);
        }
        //父进程等待子进程退出
        if ((pid = waitpid(pid, &status, 0)) < 0)
            err_sys("wait error");

        printf("%% ");

    }

    exit(0);
}

void sig_int(int sig) {
    printf("interuppted by %d\n%%", sig);
}

1.9 时间

进程时间包括:
时钟时间又称为墙上时钟时间(wall clock time),它是进程运行的时间总量。
用户CPU时间是执行用户指令所用的时间量。系统CPU时间是为该进程执行内核程序所经历的时间。

1.10 系统调用

在Unix中为每个系统调用在标准C库中设置了同名的函数。用户进程通过标准C程序来调用这些函数,然后函数又调用相应的内核服务。

从实现者的角度来看,系统调用和库函数之间有根本的区别,但从用户角度来看其区别并不重要。

系统调用提供最小接口,而库函数可以更复杂。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值