1. 系统调用
应用程序 ------------+
| |
v |
各种库 |
(C/C++标准库、Shell命令和脚本、 |
X11图形程序及库) |
| |
v |
系统调用 <-------------+
(内核提供给外界访问的接口函数,
调用这些函数将使进程进入内核态)
|
v
内核
(驱动程序、系统功能程序)
Unix/Linux 大部分系统功能是通过系统调用实现的,如 open/close。
fopen/fclose 是 C 库的函数;非系统级的;
Unix/Linux 的系统调用已被封装成 C 函数的形式,但它们并不是标准 C 的一部分。
标准库函数大部分时间运行在用户态,但部分函数偶尔也会调用系统调用,进入内核态;如 malloc/free。
程序员自己编写的代码也可以调用系统调用,与操作系统内核交互,进入内核态;如 brk/sbrk/mmap/munmap。
系统调用在内核中实现,其外部接口定义在C库中;该接口的实现借助软中断进入内核。
linux 目录结构:
Home 目录:作用是为每个账户提供账户信息,如果我们的 Linux 中有多个账户,那么在 Home 目录中可以看到和账户名对应的目录
(如果两个账户有不同的桌面,那么这些桌面的配置文件就放在相关的目录中);Home 目录可以理解为 Windows 中的“我的文档”目录;
Var 目录:包含有变动的文件,比如脱机目录(用于有效邮件、新闻、打印机等)、日志文件、格式化的手册页和临时文件,
Usr 目录:可以理解为 Windows 中的“Temp”目录;
Bin 目录:启动期间,它为普通用户提供使用的命令,Bin 目录可以理解为 Windows 中的 “System32” 和 “Program Files” 目录;
Etc 和 Dev 目录:都是与设备有关的目录,里面保存了设备的驱动程序等信息。这两个目录可以理解为 Windows 中的“drivers”目录;
Lib 目录:系统的共享目录,里面保存的文件能供系统中的多个程序调用。该目录可以理解为 Windows 中相关程序的 dll 文件集合;
Boot 目录:包含启动时转载程序所用文件,比如 LILO;
内核镜像通常保存在这里,如果有多个内核镜像,这个目录可能会增长得很快,最好把它单独保存在一个文件系统内。
该目录可以理解为 Windows 中根目录下的相关启动文件的集合。
2. time 命令:测试运行时间
real : 总执行时间
user : 用户空间执行时间(输入输出的等待时间不算)
sys : 内核空间执行时间
范例:
# time a.out
real 0m0.255s // m 分,s 秒
user 0m0.100s
sys 0m0.155s
strace 命令:跟踪系统调用
3. 一切皆文件
Linux 环境中的文件具有特别重要的意义,因为它为操作系统服务和设备,提供了一个简单而统一的接口。
在 Linux 中,(几乎)一切皆文件。
程序完全可以象访问普通磁盘文件一样,访问串行口、网络、打印机或其它设备。
大多数情况下只需要使用五个基本系统调用:
open/close/read/write/ioctl,
即可实现对各种设备的输入和输出。
Linux 中的任何对象都可以被视为某种特定类型的文件,可以访问文件的方式访问之。
广义的文件:
1) 目录文件
# vim day01
2) 设备文件
A. 控制台: /dev/console
B. 声卡: /dev/audio
C. 标准输入输出: /dev/tty
D. 空设备: /dev/null
例如:
标准输入输出:
# cat /dev/tty
输入:Hello, World !
输出:Hello, World !
输出重定向:
# echo Hello, World ! > /dev/tty
输出:Hello, World !
把 hello, world ! 写道 text.txt 文档里
# echo Hello, World ! > test.txt
# cat test.txt // 查看 text.txt 文件
内容:Hello, World !
清空 test.txt
# cat /dev/null > test.txt
# cat test.txt
内容为空;
查找名字含有 per 的文件,且权限不够的不显示:
# find / -name perl 2> /dev/null
4. 文件相关系统调用命令
open - 打开/创建文件
creat - 创建空文件
close - 关闭文件
read - 读取文件
write - 写入文件
lseek - 设置读写位置
fcntl - 修改文件属性
unlink - 删除硬链接
rmdir - 删除空目录
remove - 删除硬链接 (unlink) 或空目录 (rmdir)
unix 下没有文件名的概念,其实硬链接相当于文件名;
磁盘上的一个文件可能对应多个硬链接,硬链接通过 i 节点访问源文件;
文件被真正删除的条件是与之相关的所有硬链接文件都被删除;
软连接相当于硬链接的快捷方式,软链接又叫符号连接;
硬链接只是一个文件名,即目录中的一个条目。
软链接则是一个独立的文件,其内容是另一个文件的路径信息。
不同文件系统之间不可以建立硬链接;
但是可以建立软件连接;
ln:创建硬链接(hard link)
ln -s:创建软连接(symbolic link)
注意:
如果被 unlink/remove 删除的是文件的最后一个硬链接,并且没有进程正打开该文件,
那么该文件在磁盘上的存储区域将被立即标记为自由。
反之,如果有进程正打开该文件,那么该文件在磁盘上的存储区域,
将在所有进程关闭该文件之后被标记为自由。
a -> +-----+
X b -> | ... |
X c -> +-----+
如果被 unlink/remove 删除的是一个软链接文件,
那么仅软链接文件本身被删除,其目标不受影响。
(软链接:本身是个文件,里面存放着硬链接;)
+------+
a -> | ... | // a 是硬链接
+------+
+------+
X b -> | a | // b 和 c 是软链接
+------+
+------+
X c -> | a |
+------+
5. 文件描述符:
非负的整数,表示一个打开的文件。
由系统调用 (open/creat) 返回,被内核空间 (后续系统调用) 引用。
内核缺省为每个进程打开三个文件描述符(类似于句柄):
0 - 标准输入
1 - 标准输出
2 - 标准出错
其他描述符从 3 开始往后定义;
在 unistd.h 中被定义为如下三个宏:
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
范例:redir.c
#include <stdio.h>
int main () {
int data;
fscanf (stdin, "%d", &data);
fprintf (stdout, "%d", data);
fprintf (stderr, "%d", data);
return 0;
}
// stdout:有缓冲区,遇到换行之类的才输出;
// stderr:显示错误,无缓冲区;
下面重定向输出:
# a.out 0<i.txt 1>o.txt 2>e.txt // 一个大于号是覆盖,两个大于号是追加
把标准输入定向到 i.txt 文件里;(注意:输入是小于号,其他是大于号)
把标准输出定向到 o.txt 文件里;
把标准出错定向到 e.txt 文件里;
文件描述符的范围介于 0 到 OPEN_MAX 之间,
传统 Unix 中 OPEN_MAX 宏被定义为 63,现代 Linux 使用更大的上限,一般为 256。
应用程序 ------------+
| |
v |
各种库 |
(C/C++标准库、Shell命令和脚本、 |
X11图形程序及库) |
| |
v |
系统调用 <-------------+
(内核提供给外界访问的接口函数,
调用这些函数将使进程进入内核态)
|
v
内核
(驱动程序、系统功能程序)
Unix/Linux 大部分系统功能是通过系统调用实现的,如 open/close。
fopen/fclose 是 C 库的函数;非系统级的;
Unix/Linux 的系统调用已被封装成 C 函数的形式,但它们并不是标准 C 的一部分。
标准库函数大部分时间运行在用户态,但部分函数偶尔也会调用系统调用,进入内核态;如 malloc/free。
程序员自己编写的代码也可以调用系统调用,与操作系统内核交互,进入内核态;如 brk/sbrk/mmap/munmap。
系统调用在内核中实现,其外部接口定义在C库中;该接口的实现借助软中断进入内核。
linux 目录结构:
Home 目录:作用是为每个账户提供账户信息,如果我们的 Linux 中有多个账户,那么在 Home 目录中可以看到和账户名对应的目录
(如果两个账户有不同的桌面,那么这些桌面的配置文件就放在相关的目录中);Home 目录可以理解为 Windows 中的“我的文档”目录;
Var 目录:包含有变动的文件,比如脱机目录(用于有效邮件、新闻、打印机等)、日志文件、格式化的手册页和临时文件,
Usr 目录:可以理解为 Windows 中的“Temp”目录;
Bin 目录:启动期间,它为普通用户提供使用的命令,Bin 目录可以理解为 Windows 中的 “System32” 和 “Program Files” 目录;
Etc 和 Dev 目录:都是与设备有关的目录,里面保存了设备的驱动程序等信息。这两个目录可以理解为 Windows 中的“drivers”目录;
Lib 目录:系统的共享目录,里面保存的文件能供系统中的多个程序调用。该目录可以理解为 Windows 中相关程序的 dll 文件集合;
Boot 目录:包含启动时转载程序所用文件,比如 LILO;
内核镜像通常保存在这里,如果有多个内核镜像,这个目录可能会增长得很快,最好把它单独保存在一个文件系统内。
该目录可以理解为 Windows 中根目录下的相关启动文件的集合。
2. time 命令:测试运行时间
real : 总执行时间
user : 用户空间执行时间(输入输出的等待时间不算)
sys : 内核空间执行时间
范例:
# time a.out
real 0m0.255s // m 分,s 秒
user 0m0.100s
sys 0m0.155s
strace 命令:跟踪系统调用
3. 一切皆文件
Linux 环境中的文件具有特别重要的意义,因为它为操作系统服务和设备,提供了一个简单而统一的接口。
在 Linux 中,(几乎)一切皆文件。
程序完全可以象访问普通磁盘文件一样,访问串行口、网络、打印机或其它设备。
大多数情况下只需要使用五个基本系统调用:
open/close/read/write/ioctl,
即可实现对各种设备的输入和输出。
Linux 中的任何对象都可以被视为某种特定类型的文件,可以访问文件的方式访问之。
广义的文件:
1) 目录文件
# vim day01
2) 设备文件
A. 控制台: /dev/console
B. 声卡: /dev/audio
C. 标准输入输出: /dev/tty
D. 空设备: /dev/null
例如:
标准输入输出:
# cat /dev/tty
输入:Hello, World !
输出:Hello, World !
输出重定向:
# echo Hello, World ! > /dev/tty
输出:Hello, World !
把 hello, world ! 写道 text.txt 文档里
# echo Hello, World ! > test.txt
# cat test.txt // 查看 text.txt 文件
内容:Hello, World !
清空 test.txt
# cat /dev/null > test.txt
# cat test.txt
内容为空;
查找名字含有 per 的文件,且权限不够的不显示:
# find / -name perl 2> /dev/null
4. 文件相关系统调用命令
open - 打开/创建文件
creat - 创建空文件
close - 关闭文件
read - 读取文件
write - 写入文件
lseek - 设置读写位置
fcntl - 修改文件属性
unlink - 删除硬链接
rmdir - 删除空目录
remove - 删除硬链接 (unlink) 或空目录 (rmdir)
unix 下没有文件名的概念,其实硬链接相当于文件名;
磁盘上的一个文件可能对应多个硬链接,硬链接通过 i 节点访问源文件;
文件被真正删除的条件是与之相关的所有硬链接文件都被删除;
软连接相当于硬链接的快捷方式,软链接又叫符号连接;
硬链接只是一个文件名,即目录中的一个条目。
软链接则是一个独立的文件,其内容是另一个文件的路径信息。
不同文件系统之间不可以建立硬链接;
但是可以建立软件连接;
ln:创建硬链接(hard link)
ln -s:创建软连接(symbolic link)
注意:
如果被 unlink/remove 删除的是文件的最后一个硬链接,并且没有进程正打开该文件,
那么该文件在磁盘上的存储区域将被立即标记为自由。
反之,如果有进程正打开该文件,那么该文件在磁盘上的存储区域,
将在所有进程关闭该文件之后被标记为自由。
a -> +-----+
X b -> | ... |
X c -> +-----+
如果被 unlink/remove 删除的是一个软链接文件,
那么仅软链接文件本身被删除,其目标不受影响。
(软链接:本身是个文件,里面存放着硬链接;)
+------+
a -> | ... | // a 是硬链接
+------+
+------+
X b -> | a | // b 和 c 是软链接
+------+
+------+
X c -> | a |
+------+
5. 文件描述符:
非负的整数,表示一个打开的文件。
由系统调用 (open/creat) 返回,被内核空间 (后续系统调用) 引用。
内核缺省为每个进程打开三个文件描述符(类似于句柄):
0 - 标准输入
1 - 标准输出
2 - 标准出错
其他描述符从 3 开始往后定义;
在 unistd.h 中被定义为如下三个宏:
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
范例:redir.c
#include <stdio.h>
int main () {
int data;
fscanf (stdin, "%d", &data);
fprintf (stdout, "%d", data);
fprintf (stderr, "%d", data);
return 0;
}
// stdout:有缓冲区,遇到换行之类的才输出;
// stderr:显示错误,无缓冲区;
下面重定向输出:
# a.out 0<i.txt 1>o.txt 2>e.txt // 一个大于号是覆盖,两个大于号是追加
把标准输入定向到 i.txt 文件里;(注意:输入是小于号,其他是大于号)
把标准输出定向到 o.txt 文件里;
把标准出错定向到 e.txt 文件里;
文件描述符的范围介于 0 到 OPEN_MAX 之间,
传统 Unix 中 OPEN_MAX 宏被定义为 63,现代 Linux 使用更大的上限,一般为 256。