一、UNIX体系结构

  所有操作系统都为他们所运行的程序提供服务,典型的服务包括:执行新程序、打开文件、读文件、分配存储区等。严格意义上来说,操作系统可以定义为一种软件,它控制计算机硬件资源,提供程序运行环境。我们也将这种软件成为内核,因为它相对较小,并且位于环境的核心。内核的接口被称为系统调用。公共函数库构建在之上,普通的应用程序可以调用系统调用,也可以调用公共函数库。shell是一个特殊的应用程序,位运行其他应用程序提供了一个接口。

二、文件和目录

1.文件系统

  UNXI文件系统是目录和文件的一种层次结构,所有东西的起点称为根(root)的目录,这个目录的名称是一个字符“/”。目录是一个包含目录项的文件,由文件名和文件属性(文件类型、文件大小、文件所有者、文件权限等)组成。这里需要注意的是逻辑视图和实际存放在磁盘上的方式是不同的。UNIX文件系统的大多数实现并不在目录项中存放属性,这是因为当一个文件具有多个硬链接时,很难保持多个属性副本之间的同步。

2.文件名和路径名

  创建新目录时会自动创建两个文件名:“.”指向当前目录,“..”指向父目录,在最高层次,二者指向相同。由斜线分隔的一个或多个文件名组成的序列构成路径名,以斜线开头的路径名称为绝对路径名,否则称为相对路径名。

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<dirent.h>
  4.  
  5. int main(int argc, char *argv[])
  6. {
  7. DIR *dp;
  8. struct dirent *dirp;
  9.  
  10. if( != argc)
  11. {
  12. printf("usage: ls directory_name\n");
  13. return -;
  14. }
  15.  
  16. if(NULL == (dp = opendir(argv[])))
  17. {
  18. printf("can't open %s\n", argv[]);
  19. return -;
  20. }
  21.  
  22. while(NULL != (dirp = readdir(dp)))
  23. {
  24. printf("%s\n", dirp->d_name);
  25. }
  26.  
  27. closedir(dp);
  28. exit();
  29. }

1-1:列出一个目录中的所有文件

3.工作目录和起始目录

  每个进程都有一个工作目录,所有相对路径名都从工作目录开始解释,进程可以用chdir函数更改其工作目录。登陆时,工作目录设置为起始目录,这个目录是从口令文件中相应用户的登录项中获取的。

三、输入和输出

1.文件描述符

  文件描述符通常是一个小的非负整数,内核用以标识一个特定进程正在访问的文件。当内核打开一个先用文件或创建一个新文件时,它都返回一个文件描述符,在读写文件时,可以使用这个文件描述符。按惯例,每当运行一个新程序时,所有的shell都为其打开3个文件描述符,即标准输入、标准输出以及标准错误,如果不做特殊处理,这三个文件描述符都链接向终端。

2.不带缓冲的I/O

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

  1. #include<unistd.h>
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4.  
  5. #define BUFFSIZE 4096
  6.  
  7. int main(void)
  8. {
  9. int n;
  10. char buf[BUFFSIZE];
  11. while((n = read(STDIN_FILENO, buf, BUFFSIZE)) > )
  12. {
  13. if(write(STDOUT_FILENO, buf, n) != n)
  14. {
  15. printf("write error.\n");
  16. return -;
  17. }
  18. }
  19.  
  20. if(n > )
  21. {
  22. printf("read error.\n");
  23. return -;
  24. }
  25.  
  26. exit();
  27. }

1-2:将标准输入复制到标准输出

注释:1.头文件<unistd.h>包含了很多UNIX系统服务的函数原型,STDID_FILENO/STDOUT_FILENO,以及read/write都定义在其中。2.read函数返回其读取到的字节数,当发生错误时,read返回-1;3输入ctrl+D作为文件结束符,终止程序;

3.标准I/O

  标准I/O函数为那些不带缓冲I/O函数提供了一个带缓冲的接口。使用标准I/O函数无需担心如何选取最佳的缓冲区大小,不用像上例那样需要定义BUFFSIZE。并且还简化了对输入行的处理。

  1. #include<unistd.h>
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. int main(void)
  5. {
  6. int c;
  7. while((c = getc(stdin)) != EOF)
  8. {
  9. if(putc(c, stdout) == EOF)
  10. {
  11. printf("output error.\n");
  12. return -;
  13. }
  14. }
  15.  
  16. if(ferror(stdin))
  17. {
  18. printf("input error.\n");
  19. }
  20.  
  21. exit();
  22. }

1-3:用标准I/O将标准输入复制到标准输出

四、程序和进程

1.程序、进程和进程ID

  程序是一个存储在磁盘上某个目录中的可执行文件。内核使用exec函数将程序读入内存,并执行程序。程序的执行实例称为进程,每一个进程都有一个唯一的数字标识符,被称为进程ID(非负整数)。

  1. #include<unistd.h>
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4.  
  5. int main(void)
  6. {
  7. printf("Hello world from process ID %ld\n", (long)getpid());
  8. exit();
  9. }

1-4:打印进程ID

2.进程控制

  进程控制主要函数:fork、exec和waitpid。

  1. #include<stdlib.h>
  2. #include<stdio.h>
  3. #include<string.h>
  4. #include<unistd.h>
  5. #include<sys/wait.h>
  6.  
  7. #define MAXLINE 1024
  8.  
  9. int main(void)
  10. {
  11. char buff[MAXLINE];
  12. pid_t pid;
  13. int status;
  14.  
  15. printf("%% ");
  16.  
  17. while(NULL != (fgets(buff, MAXLINE, stdin)))
  18. {
  19. if('\n' == buff[strlen(buff) - ])
  20. {
  21. buff[strlen(buff) - ] = ;
  22. }
  23.  
  24. if( > (pid = fork()))
  25. {
  26. printf("fork error\n");
  27. return -;
  28. }
  29. else if( == pid)
  30. {
  31. execlp(buff, buff, (char *) );
  32. printf("couldn't execute:%s\n", buff);
  33. return -;
  34. }
  35.  
  36. if( > (pid == waitpid(pid, &status, )))
  37. {
  38. printf("wait pid error\n");
  39. }
  40.  
  41. printf("%% ");
  42. }
  43. }

1-5:从标准输入读命令并执行

注释:1.fgets是一个标准I/O函数,一次读取一行。和read的区别在于自己管理缓冲区,不返回读取的长度,在读取的末尾加入"\n"。而execlp要求参数以null结束,所以需要进行替换;2.fork调用一次,返回两次,在子进程中返回0,父进程返回子进程PID;3.execlp以执行从标准输入读取的命令,这就用新的程序文件替换了子进程原先执行的程序文件;4.父进程和子进程同步是通过waipid实现的。

3.线程和线程ID

  一个进程内的所有线程共享同一地址空间、文件描述符、栈以及与进程相关的属性。因为他们能访问同意存储区,所以各线程在访问共享数据时需要采取同步措施以避免不一致性。和进程ID相同, 线程也有ID,但是线程ID只在它所属的进程内其作用。

五、出错处理

  当UNIX系统函数出错时,通常会返回一个负值,而且整形变量errno通常被设置为具有特定信息的值。对于errno应当注意两条规则:1.如果没有出错,其值不会被例程清楚,因此,仅当函数的返回值指明出错时,才检验其值;2.任何函数都不会将errno值设为0.

  1. #include<unistd.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<stdio.h>
  5. #include<errno.h>
  6.  
  7. int main(int argc, char * argv[])
  8. {
  9. fprintf(stderr, "EACCES: %s\n", strerror(EACCES));
  10.  
  11. errno = ENOENT;
  12. perror(argv[]);
  13. exit();
  14. }

1-6:例示strerror和perror

注释:1.我们将程序名(argv[0])作为参数传递给main,这是一个标准的UNIX惯例。
六、用户标识

  口令文件登录项中的用户ID是一个数值,它向系统标识不同的用户。根用户的ID为0.

  1. #include<unistd.h>
  2. #include<stdlib.h>
  3. #include<stdio.h>
  4.  
  5. int main(void)
  6. {
  7. printf("uid = %d, gid = %d\n", getuid(), getgid());
  8. exit();
  9. }

1-7:打印用户ID和组ID

七、信号

  信号(signal)用于通知进程发生了某种情况。进程有以下三种处理方式:1.忽略信号;2.按系统默认方式处理;3.提供一个函数。该信号发生时调用该函数。当向一个进程发送信号时,我们必须是那个进程的所有者或者是超级用户。

  1. #include<stdlib.h>
  2. #include<stdio.h>
  3. #include<string.h>
  4. #include<unistd.h>
  5. #include<sys/wait.h>
  6.  
  7. #define MAXLINE 1024
  8.  
  9. static void sig_int(int);
  10.  
  11. int main(void)
  12. {
  13. char buff[MAXLINE];
  14. pid_t pid;
  15. int status;
  16.  
  17. if(signal(SIGINT, sig_int) == SIG_ERR)
  18. {
  19. printf("signal error\n");
  20. return -;
  21. }
  22.  
  23. printf("%% ");
  24.  
  25. while(NULL != (fgets(buff, MAXLINE, stdin)))
  26. {
  27. if('\n' == buff[strlen(buff) - ])
  28. {
  29. buff[strlen(buff) - ] = ;
  30. }
  31.  
  32. if( > (pid = fork()))
  33. {
  34. printf("fork error\n");
  35. return -;
  36. }
  37. else if( == pid)
  38. {
  39. execlp(buff, buff, (char *) );
  40. printf("couldn't execute:%s\n", buff);
  41. return -;
  42. }
  43.  
  44. if( > (pid == waitpid(pid, &status, )))
  45. {
  46. printf("wait pid error\n");
  47. }
  48.  
  49. printf("%% ");
  50. }
  51.  
  52. }
  53.  
  54. void sig_int(int signo)
  55. {
  56. printf("interrupt \n%% ");
  57. }

1-8:从标准输入读命令并执行

八、时间值

  UNIX系统为一个进程维护了3个进程时间值:1.时钟时间:进程运行的时间总量,其值与系统中同时运行的进程数有关;2.用户CPU时间:执行用户指令所用的时间量;3.系统CPU时间:为该进程执行内核程序所经历的时间。2和3之和又称为CPU时间。

九、系统调用和库函数

  从实现者的角度来看,系统调用和库函数之间有根本的区别,但从用户的角度来看,其区别不重要。用户可以替换库函数,但是不能替换系统调用。并且系统调用通常提供一种最小接口,而库函数通常提供比较复杂的功能。

APUE(1)----UNIX基础知识的更多相关文章

  1. 《UNIX环境高级编程》(APUE) 笔记第一章 - UNIX基础知识

    1 - UNIX基础知识 Github 地址 1. 操作系统 可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境.通常将这种软件称为 内核 (kernel) .( Linux 是 GN ...

  2. UNIX环境高级编程--第一章 UNIX基础知识

    第一章 UNIX基础知识 1.2 UNIX体系结构   从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境.我们将这种软件称为内核(kernel),因为 它相对较小,且 ...

  3. apue学习笔记(第一章UNIX基础知识)

    总所周知,UNIX环境高级编程是一本很经典的书,之前我粗略的看了一遍,感觉理解得不够深入. 听说写博客可以提高自己的水平,因此趁着这个机会我想把它重新看一遍,并把每一章的笔记写在博客里面. 我学习的时 ...

  4. APUE 学习笔记(一) Unix基础知识

    1. Unix 体系结构   内核的接口被称为系统调用 公用函数库构建在系统调用接口之上 应用软件既可以调用公用函数库,也可以直接进行系统调用   2. 文件和目录 目录操作函数:opendir--- ...

  5. 第一章:UNIX基础知识

    本章内容主要是为了学习UNIX的基本知识和一些最基本的系统函数. 学习的关键就是跟随者书本敲代码.本节遇到的第一个问题就死本书的apue.h这个文件:一开始没有注意这个文件,盲目的去百度,一番百度之后 ...

  6. UNIX基础知识之程序和进程

    一.程序 程序(program)是存放在磁盘上.处于某个目录中的一个可执行文件.使用6个exec函数中的一个由内核将程序读入存储器,并使其执行. 二.进程和进程ID 程序的执行实例被称为进程(proc ...

  7. 《UNIX环境高级编程》笔记——1.UNIX基础知识

    这一章节侧重一些基本概念和书中用到的一些名词. 一.引言 所有的操作都提供服务,典型的服务包括:执行新程序.打开文件.读写文件.分配存储区以及获得当前时间等. 二.UNIX体系结构 其实linux常见 ...

  8. UNIX,基础知识,文件IO,文件和目录

    2015.1.27星期二,早晨阴天,中午下雪了今天上午老师不上课,程序语句,记一下:main(void){ int c; while((c = getc(stdin)) != EOF) if(putc ...

  9. UNIX基础知识之时间值

    本篇博文内容摘自<UNIX环境高级编程>(第二版),仅作个人学习记录所用.关于本书可参考:http://www.apuebook.com/. 长期以来,UNIX系统一直使用两种不同的时间值 ...

随机推荐

  1. Yii2 Post请求的时候出现400错误

    Bad Request (#400) Unable to verify your data submission.   http://www.yiiframework.com/forum/index. ...

  2. 2、通过HBase API进行开发

    一.将HBase的jar包及hbase-site.xml添加到IDE 1.到安装HBase集群的任意一台机器上找到HBase的安装目录,到lib目录下下载HBase需要的jar包,然后再到conf目录 ...

  3. 【转】Apache JMeter web性能测试实例

    Apache JMeter是可以对利用HTTP或FTP服务器的应用程序进行测试的工具.它是基于Java的,通过所提供的API它还具有高度可扩展性.典型的JMeter测试包括创建循环和线程组.循环使用预 ...

  4. 【转】Jmeter性能测试报告解析

    Jmeter报告解析 1.Aggregate Report 解析 Aggregate Report 是 JMeter 常用的一个 Listener,中文被翻译为“聚合报告”.今天再次有同行问到这个报告 ...

  5. js前端处理datetime时间类型

    MySql数据库日期字段定义的是datetime类型,(顺带插入MySql数据库datetime类型可以用这个: str_to_date('2008-4-2 15:23:28','%Y-%m-%d % ...

  6. 1134 Vertex Cover

    题意:给出一个图和k个查询,每个查询给出Nv个结点,问与这些结点相关的边是否包含了整个图的所有边. 思路:首先,因为结点数较多,用邻接表存储图,并用unordered_map<int,unord ...

  7. linux lcd设备驱动剖析三

    上一节文章中详细地剖析了probe函数,但是从始至终都没有看到打开读写文件接口的操作函数,只看到了下面这个操作结构体 [cpp] view plain? static struct fb_ops s3 ...

  8. python's sixteenth day for me 员工信息表

    import os user_dic = { 'username':None, 'password':None, 'login':True } flag = False name_list = ['i ...

  9. @Value关于static字段的注入

    @Component public class BaseCode { //应用key public static String APP_KEY; //应用密钥 public static String ...

  10. LCS(详解)

    一,问题描述 给定两个字符串,求解这两个字符串的最长公共子序列(Longest Common Sequence).比如字符串1:BDCABA:字符串2:ABCBDAB 则这两个字符串的最长公共子序列长 ...