免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 雨丝风片
打印 上一主题 下一主题

[FreeBSD] 【FreeBSD system programming 】中文翻译计划及所有异义提交处 [复制链接]

论坛徽章:
0
111 [报告]
发表于 2006-02-18 12:49 |只看该作者
已翻译章节的 pdf 版本,论坛上传不了,临时放在下面地址:

http://www.soforge.com/freebsdsp.pdf

整理时自己加了一些排版规则:

1. 中文和英文与数字之间加一个空格。
2. 中文语句中的标点符号都用全角。

还改动了几个明显的错别字,字体用的是方正的,凑合着可以看

附件是 TeX 源码,有兴趣的朋友,可以把版面改得更漂亮一些。

[ 本帖最后由 szjungle 于 2006-2-19 18:27 编辑 ]

freebsdsp.tar.gz

49.36 KB, 下载次数: 36

freebsdsp.tar.gz

论坛徽章:
0
112 [报告]
发表于 2006-02-18 13:00 |只看该作者
原帖由 szjungle 于 2006-2-18 12:49 发表
已翻译章节的 pdf 版本,论坛上传不了,临时放在下面地址:

http://www.soforge.com/freebsdsp.pdf

整理时自己加了一些排版规则:

1. 中文和英文与数字之 ...


漂亮!辛苦了!

先收藏了,期待我们最终的版本!

另外有两个建议:
1、能不能再加上书签,这样阅读起来更方便一些
2、代码你是用的listing宏包么?能不能弄点效果,比如阴影什么的,觉得这样会更漂亮一些,

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
113 [报告]
发表于 2006-02-18 13:07 |只看该作者
漂亮,很漂亮,兄弟费心了。

论坛徽章:
0
114 [报告]
发表于 2006-02-18 13:21 |只看该作者
原帖由 雨丝风片 于 2006-2-18 13:00 发表

漂亮!辛苦了!

先收藏了,期待我们最终的版本!

另外有两个建议:
1、能不能再加上书签,这样阅读起来更方便一些
2、代码你是用的listing宏包么?能不能弄点效果,比如阴影什么的,觉得这样会更漂 ...


一般中文标签要用 gbk2uni 程序处理一下,我现在改成 UTF8 编码,这个程序用不成了,还没找到解决方法

我不熟悉 listing 宏包,平时就用 verbatim 和 fancyvrb。要不要加阴影,考虑到打印,不知道哪种效果好一些。

论坛徽章:
0
115 [报告]
发表于 2006-02-18 13:25 |只看该作者
原帖由 szjungle 于 2006-2-18 13:21 发表


一般中文标签要用 gbk2uni 程序处理一下,我现在改成 UTF8 编码,这个程序用不成了,还没找到解决方法

我不熟悉 listing 宏包,平时就用 verbatim 和 fancyvrb。要不要加阴影,考虑到打印,不知道哪种效 ...


嗯,是有这个问题,我原来也一直用gbk2uni 处理完事,

至于阴影,我倒是没考虑到打印的问题,多此一举,其实你的文档已经相当漂亮了!

论坛徽章:
0
116 [报告]
发表于 2006-02-18 14:04 |只看该作者
***继续,修复了先前版本翻译不是很妥的地方,不知道代码怎么插入,帮忙整理整理格式,多谢***

本章示范(示例)代码:http://www.khmere.com/freebsd_book/src/05/index.html


5.1  基本输入输出

一般来说,Unix信奉简单设计的哲理。"一切都是文件"是个很强大的特征--这就意味着你所编辑的文本文件具有和调制解调器、打印机或网卡相同的编程接口,就像编辑文本文件一样,你应该能够对它们(被编辑文件)执行基本的读、写操作等等。尽管这个想法现行的实现不完美,BSD Unix实际上做到非常接近了,这也正是BSD又一个强大的地方--简洁而优雅。有些不是真实的文件而是设备,它们的入口在/dev目录下,有些设备只能用于特殊的操作,如块的读、写,一个极端的例子是以太网设备,甚至它(以太网设备)在FreeBSD 5之前在/dev下面没有入口。

操作系统看待每件事都像文件,一个好的示范是Plan 9,Plan 9用文件实现一切,甚至以太网和网络协议;更详细的信息可以参考Plan 9的主页http://www.cs.bell-labs.com/plan9dist/

一般来说,文件是计算机上数据最基本、最初级的表现形式,本质上是数据一位一位的线性序列。当用exec命令执行编译过的程序时,系统将把二进制文件读入内存,代码将在分配到内存地址空间后被执行,程序被定位在什么位置跟exec命令有关,它可以在软磁盘,硬盘,光驱,甚至是加载的另一半还分布在世界其他角落的网络文件系统上;跟基于网络链路发送数据一样,内容被顺序地一位一位地读入。当一个程序发送数据的时候,数据本身是一位一位的线性序列,有些时候叫做“流”,程序不关心它是否基于网络链路发送数据,它仅仅写数据;这两种最基本的操作,读跟写,是计算鸡用到的最多的。

本章将涉及最基本的I/O子系统跟进程资源。


5.2  基本输入输出
UNIX进程打开文件的时候,会保存文件描述符的参考值,该值是一个整数,不论何时在UNIX系统上创建一个进程,都会给它3个文件描述符:
    0   标准输入
    1   标准输出
    2   标准错误

这些值能够用于描述终端、文件的读写,甚至设置其他进程的描述。使shell重定向, cat /etc/hosts >> hosts.out, shell将打开文件hosts.out并且将cat /etc/hosts做为自己的参数执行。不管怎样,当cat进程写到标准输出后(1),结果不会被tty得到,而是输出到hosts.out文件。(cat程序根本不知道写入了文件系统的文件,还是写入到标准输出的文件描述符,我们将在这章的后面一点看到究竟是怎么实现的)

最基本的两个操作描述符是Open和Close函数

Open函数
  1.         int     open(const char *path, int flags, /*  mode */ );,
复制代码

成功地调用这个函数后,Open函数将返回文件及参数的描述符,这个整型描述符在进程文件描述表内生成索引。该描述符的结构能够让内核知道如何操作这个文件。在BSD上,这个结构叫做filedesc,并且能够在/usr/include/sys/filedesc.h这个头文件中找到。当进程要在这个描述符上执行一些操作的时候,它将要求文件描述符为读、写、可执行操作指定一个整数值。

内核保存了所有文件描述符的基准值,这些基准值将在时进程打开、复制它或者已经处于打开状态的文件描述符执行exec调用、跨越fork的过程中增加。当这个参考值为0的时候,文件关闭。意思是,如果你有一个程序执行fork或者exec调用,并且close-on-exec位没有指定,基准值将增加;并且当一个新的程序执行了fork或者exec调用,基准值将继续增加。所以文件一直处于打开状态,直到基准值被设置为0,或者直到所有的进程关闭它,或者退出。

Close函数
  1.         int        close(int fd);
复制代码

当进程想移除或者关闭一个打开的文件描述符的时候,它将调用close函数。这将关闭指定的文件描述符,并且减少文件描述符的参考值。这个过程很像 exit————当一个进程执行exit,所有打开的文件描述符跟进程一起被自动地减少,自从文件参考值设为0,内核将释放所有的文件入口的副本.

getdtablesize函数
  1.         int        getdtablesize();
复制代码

getdtablesize函数返回文件描述表的大小,它能用作检查系统限制,你也能够用下面的命令做相同的事情。
  1. bash$ sysctl kern.maxfilesperproc
  2. kern.maxfilesperproc: 3722
复制代码


依赖于你的系统,你能够在系统运行的时候调整它,或者从新编译你的内核,这个函数不能检查当前进程打开了多少文件,(跟getdtablesize一样)仅仅返回你的进程能够打开文件的最大个数。

fcntl函数
  1.         int        fcntl(int fd, int cmd, ...);
复制代码

fcntl函数允许进程操作文件描述符,fcntl函数至少需要指定两个参数,一个有效的文件描述符,一个命令。根据使用的命令,决定fnctl是否需要第三个参数,下面为命令定参数义了一些值。在FreeBSD上,你能在/usr/include/fcntl.h头文件中找到它们。
  1.         #define F_DUPFD        0
复制代码

F_DUPFD用作创建一个新的很像原型的文件描述符,(你能够用dup调用做到相同的事情,将在晚些时候涉及到),当成功执行带F_DUPFD标记的fcntl函数,fcntl将返回下面属性之一的新的文件描述符:

  • 假如指定了第三个参数,描述符返回的值比最小可用的描述符,该值等于或者比给定的第三个参数的值大一点,返回的描述符将参照指定给fcntl第一个参数的文件描述符
  • 假如fcntl指定的文件描述符是一个文件,新文件描述符将有相同的文件偏移量,并且新文件描述符将有相同的访问方式(如:O_RDONLY,O_RDWR,o_WRONLY)
  • 新文件描述符将共享文件状态标记
  • 新文件的“close-on-exec”标志将被关闭,即新的文件描述符在exec调用之后仍将保持打开。


F_GETFD命令
  1.         #define  F_GETFD     1
复制代码

F_GETFD命令用作获取"close-on-exec"标记的状态,跟FD_CLOSEXEC相与后返回值要么为0,要么为1。如果返回0,close-on-exec标记没有被设置过,那么文件描述符将保持调用交叉执行调用(so the file descriptor will remain open across exec calls.),假如是1,close-on-exec标志被设置过,文件描述符将在成功调用一个exec函数后被关闭。

F_SETFD命令
  1.         #define  F_SETFD     2
复制代码

F_SETFD命令用作设置文件描述符的close-on-exec标志位。第三个参数要么是FD_CLOEXEC,设置close-on-exec标记,要么是0,取消close-on-exec标记的设置。

F_GETFL和F_SETFL命令
  1.         #define  F_GETFL    3
  2.         #define  F_SETFL    4
复制代码

F_GETFL命令将使fcntl返回当前文件描述符状态标记,当返回值加上O_ACCMODE(#define O_ACCMODE 0x0003)能够获取到打开的方式,F_SETFL命令将根据第三个参数设置文件状态标记。

公共的标记
下面这些标记也用作调用open,并且只能被跟上期望的标记调用open函数设置,这是最常见的,检查你系统的头文件能够查到那些值

  1. #define  O_RDONLY 0x0000
复制代码

如果O_RDONLY标记被设置,那么文件只能以只读方式打开。注意这个O_RDONLY标记只能在打开的时候被设置,它不能被fnctl加F_SETFL命令设置。

  1. #define  O_WRONLY 0x0001
复制代码

如果O_WRONLY标记被设置,那么文件只能以只写方式打开。这个标记只能被open设置,不能被fcntl加F_SETFL命令设置。

  1. #define  O_RDWR      0x0002
复制代码

如果O_RDWR标记被设置,那么文件以可读可写方式打开。这个标记也只能被open调用设置。

  1. #define  O_NONBLOCK  0x0004
复制代码

如果O_NONBLOCK标记被设置,文件描述符将不被阻塞而被直接返回替代。一个例子是打开tty。如果用户不在终端调用里输入任何东西,read将被阻塞,直到用户有输入,当O_NONBLOCK标记被设置,read调用将直接返回设置到EAGAIN的值

  1. #define  O_APPEND 0x0008
复制代码

如果O_APPEND标记被设置,文件将以追加方式打开,并且将从文件末尾开始写入。

  1. #define  O_SHLOCK 0x0010
复制代码

如果O_SHLOCK标记被设置,文件描述符将在文件上生成一个共享锁,在文件上设置了共享锁,多个进程能在同一个文件够执行操作,文件共享锁的详细信息,可用看fnctl函数的F_GETLK跟F_SETL命令。

  1. #define  O_EXLOCK 0x0020
复制代码

如果O_EXLOCK标记被设置,文件描述符将在文件上生成一个可执行锁,一样,更详细的描述可以参照fcntl函数的F_SETLK跟F_GETLK命令。

  1. #define  O_ASYNC     0x0040
复制代码

如果O_ASYNC标记被设置,进程集将被发送的SIGIO信号通知,在文件描述符号的IO是可用的。详细的描述请参照信号那一章。

  1. #define  O_FSYNC     0x0080
复制代码

如果O_FSYNC标记被设置,所有写到文件描述符的写操作将不被内核缓存,取而代之的是将被写到介质,并且所有的写调用都将被阻塞,直到内核完成(写操作)。

  1. #define  O_NOFOLLOW  0x0100
复制代码

如果O_NOFOLLOW标记被设置,假如文件是一个符号连接,open调用将会失败。如果在一个有效的文件描述符上设置了这个标志,那么当前文件就不是一个符号连接。

  1. #define  O_CREAT     0x0200
复制代码

如果O_CREAT标记被设置,假如执行open调用的时候文件不存在,那么文件可用被创建。(这个错误的拼写很有趣;when one of the original creators of C was asked "What one thing would you change about C?" he replied, "I would change O_CREAT to O_CREATE!", or at least how the rumor goes)

  1. #define  O_TRUNC     0x0400
复制代码

如果O_TRUNC标记被设置,成功地调用open后文件将被截除。

  1. #define  O_EXCL      0x0800
复制代码

当O_EXCL标记被设置,假如文件已经存在,open调用将产生一个错误。

  1. #define F_GETOWN          5
复制代码

F_GETOWN命令用于描述符获取当前进程或者进程集收到的SIGIO信号。如果这个值是一个正数,它表示一个进程,负数表示一个进程集。

  1. #define F_SETOWN  6
复制代码

当IO就绪的时候,F_SETOWN命令用作设置进程或者进程集使其接收SIGIO信号,指定一个进程,用一个正数(一个进程ID)作为fcntl的第三个参数,否则,用一个负数作为fcntl的第三个参数指定进程集。

[ 本帖最后由 雨丝风片 于 2006-2-18 16:08 编辑 ]

论坛徽章:
0
117 [报告]
发表于 2006-02-18 16:17 |只看该作者
原帖由 horseman 于 2006-2-18 14:04 发表
***继续,修复了先前版本翻译不是很妥的地方,不知道代码怎么插入,帮忙整理整理格式,多谢***

本章示范(示例)代码:http://www.khmere.com/freebsd_book/src/05/index.html


5.1  基本输 ...


帮你修改了一下代码格式,你看看还行不行?

已经将这部分添加到发布贴里去了,进度条也已更新!

论坛徽章:
0
118 [报告]
发表于 2006-02-18 17:29 |只看该作者
3.5是子进程 pdf里写成子例程了

论坛徽章:
0
119 [报告]
发表于 2006-02-19 18:27 |只看该作者
原帖由 孙轩 于 2006-2-18 17:29 发表
3.5是子进程 pdf里写成子例程了


已经改正

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
120 [报告]
发表于 2006-02-20 11:23 |只看该作者
4.4 信号处理
现在我们知道何时会产生信号,也知道如何发送信号,那么我们怎么处理它们呢?

signal函数

signal系统函数调用提供了一种最简单的范例。然而,由于C原形声明的缘故使它看起来比实际复杂。signal函数将一个给定的函数和一个特定的信号联系。这里是FreeBSD中的定义(和一个typedef一起):
typedef void (*sig_t) (int);

sig_t   signal(int sig, sig_t func);

第一个参数是目标信号,可以是上面列举的所有信号中的任何一个。func参数是一个指针,指向某个处理该信号的函数。这个处理信号函数带有一个int型参数,并应返回void。signal函数中的func参数也可以设定为下面的一些值:
SIG_IGN: 如果func参数被设置为SIG_IGN,该信号将被忽略。

SIG_DFL: 如果func参数被设置为SIG_DFL,该信号会按照确定行为处理。


sigaction函数

sigaction函数是一个比signal更通用的方案。第一个参数是目标信号。下一个名为act的参数(指向)sigaction结构,该结构包含一些用于信号处理的信息。最后一个参数oact是一个指针,指向一个可以存储上一次设置信号处理的信息的地方。
int  sigaction(int sig, const struct sigaction *act, struct sigaction *oact);

sigaction结构有下面这些个成员:
void     (*sa_handler)(int);

这个结构成员是一个指向函数的指针,该函数带有一个简单的整形参数,并返回(void)。这与signal函数的func参数相同,也可以被设置为SIG_IGN和SIG_DFL,并且与调用signal得到的效果也一样。
void     (*sa_sigaction)(int, siginfo_t *, void *);

该结构成员是一个指向函数的指针,返回(void)并需要三个参数。这些参数依次为:一个整形参数指定信号发送;一个指向siginfo_t结构的指针用来保存关于信号的信息;最后一个也是一个指针,指向信号交付时的特定上下文(context)空间。
sigset_t sa_mask;

该结构成员是一个位掩码(bitwise mask),用来指示信号交付时哪些信号会被阻塞。阻塞SIGKILL和SIGSTOP信号的做法会被忽略。接下来,被阻塞的信号将被推迟,直到它们被开启(unblock)。参见sigprocmask获得更多关于全局掩码(global masks)的信息。
int      sa_flags;

该数据成员是一个拥有下面这些标志的位掩码:
SA_NOCLDSTOP: 如果SA_NOCLDSTOP位被置位并且目标信号是SIGCHLD,除非子进程退出,而在子进程停止(stop)时父进程将不会收到通知。

SA_NOCLDWAIT: SA_NOCLDWAIT标志会阻止子进程成为僵尸进程。在目标信号是SIGCHLD的时候使用。如果进程设置了这个标志,接着调用某个wait系统调用,进程将被阻塞直到子进程全部终止,最后返回-1(译注:此处在APUE2ed中的解释是返回1),设置errno全局变量为ECHILD。

SA_ONSTACK: 一些时候需要在特定的堆栈上进行信号的处理。sigaction系统调用提供了这个方式。如果该位被置位,那么信号将会被交付到指定的堆栈上。

SA_NODEFER: 如果SA_NODEFER位被置位,那么当前信号正被处理时,系统不会屏蔽该信号以后的交付。

SA_RESETHAND: 如果SA_RESETHAND被置位,一旦信号被交付,信号处理句柄将被置为SIG_DEF。

SA_SIGINFO: 被置位时,由结构体sigaction 的成员sa_sigaction指向的函数被使用。注意:使用SIG_IGN或SIG_DFL时不应该设置这个标志。成功调用sigaction之后,返回0或-1,并且将error设置成相关错误值。


4.5信号掩码(阻塞与开启信号)

进程可以阻塞或设置某个信号。一旦该信号被阻塞,关于它的交付将被推迟,直到进程重新开启它。在这样的情况下是非常有用的:进程进入代码中某个部分,不能被中断但仍希望可以接受、处理可能丢失的信号。可靠交付信号的能力直到4.2BSD引入之后(不久被SVR3采用),操作系统才拥有该能力。

随着可靠信号的出现,信号的生命和交付(life and delivery)都有所改变。信号可以在之前产生和交付。现在,一旦信号是挂起的(pending),进程可以在接收它之前决定怎么处理。进程可能会去处理它,也可能设置为缺省行为,或者丢弃信号

注意:如果许多信号都挂起,系统将会首先交付会改变进程状态的信号,例如SIGBUS。

sigprocmask

任何进程可以使用sigprocmask函数来阻塞信号。语法如下:
int     sigprocmask(int how, const sigset_t *set, sigset_t *oset);

sigprocmask函数会修改或检查(modify or examine)当前信号掩码。当set参数不是null的时候,sigprocmask的行为和第一个参数how有关。函数行为和相关意义列举如下:
SIG_BLOCK: 在set参数中指定的信号被阻塞,并且添加进阻塞信号列表。

SIG_UNBLOCK: 在set参数中指定的信号会从信号掩码中移除。

SIG_SETMASK: set参数将完全替代当前信号掩码。如果oset参数不为null,则会被设置为前一个信号掩码。如果set值是null,how参数被忽略并且信号掩码保持不变。所以,为了检查信号掩码,我们可以将传入set null值,oset为非null值来调用sigprocmask函数。一旦掩码得到之后,你可能需要对他进行检查或操作。可以使用下面的过程(routine)。注意当前这些过程是宏的实现。
  1. int    sigemptyset(sigset_t *set)
复制代码

如果调用这个过程,set参数将被初始化指向一个空信号集。
  1. int    sigfillset(sigset_t *set)
复制代码

如果调用这个过程,set参数将被初始化指向一个包括所有信号的信号集。
  1. int   sigaddset(sigset_t *set, int signo)
复制代码

如果调用这个过程,signo指定的信号将被添加进set参数指定的信号集。
  1. int    sigdelset(sigset_t *set, int signo)
复制代码

如果调用这个过程,signo指定的信号将从set参数指定的信号集中移除。
  1. int   sigismember(const sigset_t *set, int signo)
复制代码

如果调用这个过程,如果由signo指定的信号存在于set参数指定的信号集中时,返回1,否则返回0。
  1. int     sigpending(sigset_t *set);
复制代码

进程可以使用sigpending函数去查出当前那些信号被挂起。sigpending函数会返回一个包含所有挂起信号的掩码。该掩码可以使用上面介绍的过程去检查。sigpending成功时返回0,否则返回-1,并且设置errno为相应错误值。

(怎么还有25%呢)

[ 本帖最后由 gvim 于 2006-2-20 11:24 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP