Chinaunix首页 | 论坛 | 博客
  • 博客访问: 202560
  • 博文数量: 37
  • 博客积分: 4624
  • 博客等级: 上校
  • 技术积分: 433
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-10 14:06
文章分类

全部博文(37)

文章存档

2012年(6)

2011年(25)

2008年(6)

我的朋友

分类: LINUX

2008-06-28 01:31:21

第一章 UNIX基础知识

1.2 UNIX体系结构

可将操作系统定义为一种软件-内核(kernel)。
内核的接口称为系统调用(system call)。
公用函数库建立在系统调用接口之上,应用软件可以使用公用函数库,也可以使用系统调用。
shell是一种特殊的应用程序,它为运行其他应用程序提供了一个接口。

1.3 登录

1 登录名
系统口令文件通常是:/etc/passwd 文件。
口令文件中的登录项由7个冒号分割的字段组成,它们是:
登录名,加密口令,数值用户ID,数值组ID,注释字段,起始目录,shell程序。
如:
sar:x:205:105:Stephen Rago:/home/sar:/bin/ksh
目前所有系统已将加密口令移到另一个文件中。
2 shell
shell是一个命令行解释器,它读取用户输入,然后执行命令。
Linux默认shell是Bourne-again shell。

1.4 文件和目录

1 文件系统
UNIX文件系统是目录和文件组成的一种层次结构,目录的起点称为根root,其名字是一个字符/。
2 文件名
目录中的各个名字称为文件名。
创建新目录的同时自动创建俩个文件名:.(当前目录),..(父目录),根目录中点与点点相同。
3 路径名
一个或多个以斜线分割的文件名序列构成路径名。
4 工作目录
每个进程都有一个工作目录,也叫当前工作目录。
5 起始目录
登录时,工作目录设置为起始目录(home directory),即为口令文件中设置值。

[程序清单1-1]

  1. #include "stdio.h"
  2. #include "dirent.h"

  3. int
  4. main(int argc, char *argv[])
  5. {
  6.     DIR *dp;
  7.     struct dirent *dirp;    
  8.     if(argc != 2) {
  9.         printf("no input a dirname!\n");
  10.         exit(0);
  11.     }    
  12.     if((dp = opendir(argv[1])) == NULL) {
  13.         printf("can't open %s\n", argv[1]);
  14.         exit(0);
  15.     }    
  16.     while((dirp = readdir(dp)) != NULL) {
  17.         printf("%s\n", dirp->d_name);
  18.     }    
  19.     closedir(dp);
  20.     exit(0);
  21. }

 

1.5 输入和输出

1 文件描述符
文件描述符通常是一个小的非负整数,内核用它标识一个特定进程正在访问的文件。读写文件时需要使用它。
2 标准输入,标准输出,标准出错
每当运行一个新程序时,所有的shell都为其打开三个文件描述符:标准输入,标准输出,标准出错。
3 不用缓冲的I/O
函数open,read,write,lseek,close提供了不用缓冲的I/O的输入输出。这些函数都使用文件描述符。
键入文件结束字符通常为:Ctrl+D。

[程序清单1-2]

  1. #include "unistd.h"
  2. #include "stdio.h"

  3. #define BUFFSIZE 4096

  4. int
  5. main(void)
  6. {
  7.     int n;
  8.     char buf[BUFFSIZE];
  9.     while((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) {
  10.         if(write(STDOUT_FILENO, buf, n) != n) {
  11.             printf("write error.\n");
  12.             exit(0);
  13.         }
  14.     }
  15.     if(n < 0) {
  16.         printf("read error.\n");
  17.     }
  18.     exit(0);
  19. }

 

4 标准I/O
标准I/O函数提供一组对不用缓冲I/O函数的带缓冲的接口。

[程序清单1-3]

  1. #include "stdio.h"
  2. int
  3. main(void)
  4. {
  5.     int c;
  6.     while ((c = getc(stdin)) != EOF) {
  7.         if(putc(c, stdout) == EOF) {
  8.             printf("output error\n");
  9.             exit(0);
  10.         }
  11.     }
  12.     if (ferror(stdin)) {
  13.         printf("input error\n");
  14.     }
  15.     exit(0);
  16. }

1.6 程序和进程

1 程序
程序是存放在磁盘上的一个可执行文件。
2 进程和进程ID
程序的执行实例被称为进程(process)。
UNIX确保每个进程都有一个唯一的非负整数标识符,称为进程ID。

[程序清单1-4]

  1. #include "stdio.h"
  2. #include "unistd.h"

  3. int
  4. main(void)
  5. {
  6.     printf("hello world from process ID %d\n", getpid());
  7.     exit(0);
  8. }

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

[程序清单1-5]

  1. #include
  2. #include
  3. #include "stdio.h"

  4. #define MAXLINE 1024

  5. int
  6. main(void)
  7. {
  8.     char buf[MAXLINE];
  9.     pid_t pid;
  10.     int status;
  11.     printf("%%");
  12.     while (fgets(buf, MAXLINE, stdin) != NULL) {
  13.         if (buf[strlen(buf) - 1] == '\n') {
  14.             buf[strlen(buf) - 1] = 0;
  15.         }

  16.         if ((pid = fork()) < 0) {
  17.             printf("fork error\n");
  18.         }
  19.         else if (pid == 0) {
  20.             execlp(buf, buf, (char*)0);
  21.             printf("couldn't execute: %s\n", buf);
  22.             exit(127);
  23.         }
  24.         if ((pid = waitpid(pid, &status, 0)) < 0) {
  25.             printf("waitpid error\n");
  26.         }
  27.         printf("%%");
  28.     }
  29.     exit(0);
  30. }

4 线程和线程ID
一个进程中可以包含多个线程。
每个线程也都有一个非负整数标识符,称为线程ID。

1.7 出错处理

UNIX函数出错时,常常返回一个负值,而且全局整型变量errno通常被设置为含有附加信息的一个值。
C标准定义了俩个函数来打印出错信息: #include char *strerror(int errnum); 此函数返回errnum(通常就是errno)代表的出错信息字符串指针。 #include void perror(const char *msg); 该函数首先输出msg指向的字符串,然后是一个冒号,一个空格,接着是对应与errno值的出错信息,然后是一个换行符。

[程序清单1-6]
  1. #include "stdio.h"
  2. #include "string.h"
  3. #include

  4. int
  5. main(int argc, char *argv[])
  6. {
  7.     fprintf(stderr, "EACCES: %s\n", strerror(EACCES));
  8.     errno = ENOENT;
  9.     perror(argv[0]);
  10.     exit(0);
  11. }

1.8用户标识

1 用户ID
口令文件登录项中包括用户ID,用户ID为0的用户为根root或超级用户superuer。
2 组ID
口令文件登录项中包括用户的组ID,组被用于将若干用户分配到不同的项目组或部门中去,这种机制允许同组的各个成员共享资源。
组文件将组名映射为数字组ID,它通常是/etc/group.

[程序清单1-7]
  1. #include "stdio.h"

  2. int
  3. main(void)
  4. {
  5.     printf("uid = %d, gid = %d\n", getuid(), getgid());
  6.     exit(0);
  7. }

3 附加组ID
除了口令文件中对一个用户指定一个组ID外,还允许一个用户属于额外的组,登录时,读文件/etc/group,寻找该用户作为其成员的16个记录项就可得到该用户的附加组ID。
大多数系统最少支持16个附加组。

1.9 信号

信号(signal)是通知进程已发生某种情况的一种技术。
进程处理信号的三种方式:
1 忽略该信号。
2 按系统默认方式处理。
3 提供一个函数,信号发生时则调用该函数。

[程序清单1-8]
  1. #include
  2. #include
  3. #include "stdio.h"
  4. #define MAXLINE 1024

  5. static void sig_int(int);

  6. int
  7. main(void)
  8. {
  9.     char buf[MAXLINE];
  10.     pid_t pid;
  11.     int status;
  12.     if(signal(SIGINT, sig_int) == SIG_ERR) {
  13.         printf("signal error\n");
  14.     }
  15.     printf("%%");
  16.     while(fgets(buf, MAXLINE, stdin) != NULL) {
  17.         if(buf[strlen(buf) - 1] == '\n')
  18.         {
  19.             buf[strlen(buf) - 1] = 0;
  20.         }

  21.         if((pid = fork()) < 0) {
  22.             printf("fork error\n");
  23.         }
  24.         else if(pid == 0) {
  25.             execlp(buf, buf, (char*)0);
  26.             printf("couldn't execute: %s\n", buf);
  27.             exit(127);
  28.         }
  29.         if((pid = waitpid(pid, &status, 0)) < 0) {
  30.             printf("waitpid error\n");
  31.         }
  32.         printf("%%");
  33.     }
  34.     exit(0);
  35. }

  36. void
  37. sig_int(int signo)
  38. {
  39.     printf("interrupt\n%%");
  40. }

1.10 时间值

长期以来,UNIX系统一直使用俩中不同的时间值:
1 日历时间
该值是自1970-01-01 00:00:00以来国际标准时间(UTC)所经过的秒数累计值。
系统基本数据类型time_t用于保持这种时间值。
2 进程时间
也被称为CPU时间,用以度量进程使用的中央处理器资源。进程时间以时钟滴答计算,历史上曾经取每秒50,60,100个滴答。
系统基本数据类型clock_t用于保存这种时间值。可以用sysconf函数得到每秒时钟滴答数。
当度量一个进程执行时间时,UNIX系统使用三个进程时间值:
时钟时间:进程运行的时间总量,其值与系统中同时运行的进程数有关。
用户CPU时间:执行用户指令所用的时间。
系统CPU时间:执行内核程序所经历的时间。

阅读(1274) | 评论(0) | 转发(0) |
0

上一篇:使用make

下一篇:第二章 UNIX标准化及实现

给主人留下些什么吧!~~