免费注册 查看新帖 |

Chinaunix

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

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

论坛徽章:
0
81 [报告]
发表于 2006-02-16 16:39 |只看该作者
原帖由 雨丝风片 于 2006-2-16 15:43 发表


还是你手快!

我把两个冒号也补上了,另外,第二个问题我先持保留意见,看看szjungle是否认可?


都可以,汉语中意会的东西太多了

论坛徽章:
0
82 [报告]
发表于 2006-02-16 17:02 |只看该作者
*** 翻译的很不好,请多多包含,后面的章节将会继续,请大家一起校验,多谢了先 ***


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

一般来说,Unix信奉"Simple design"的哲理。"everything is a file"是一个非常强大的特征--it means a text file you edit has the same programmatic interface as a modem, printer, or network card。(它意味着当你编辑的那个文本文件有和调制解调器 打印机 和网卡有同样的programmatic接口),就像编辑文本文件一样,你应该能够对它们(被编辑文件)执行基本的读、写操作等等。尽管这个想法现行的实现不完美,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函数
        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函数
        int        close(int fd);
当进程想移除或者关闭一个打开的文件描述符的时候,它将调用close函数。这将关闭指定的文件描述符,并且减少文件描述符的参考值。这个过程很像exit————当一个进程执行exit,所有打开的文件描述符跟进程一起被自动地减少,自从文件参考值设为0,内核将释放所有的文件入口的副本.

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

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

fcntl函数
        int        fcntl(int fd, int cmd, ...);
fcntl函数允许进程操作文件描述符,fcntl函数至少需要指定两个参数,一个有效的文件描述符,一个命令。根据使用的命令,决定fnctl是否需要第三个参数,下面为命令定参数义了一些值。在FreeBSD上,你能在/usr/include/fcntl.h头文件中找到它们。
        #define F_DUPFD        0
F_DUPFD用作创建一个新的很像原型的文件描述符,(你能够用dup调用做到相同的事情,将在晚些时候涉及到),当成功执行带F_DUPFD标记的fcntl函数,fcntl将返回下面属性之一的新的文件描述符,
        加入指定了第三个参数,描述符返回的值比最小可用的描述符,该值等于或者比给定的第三个参数的值大一点,返回的描述符将参照指定给fcntl第一个参数的文件描述符
        假如fcntl指定的文件描述符是一个文件,新文件描述符将有相同的文件偏移量,并且新文件描述符将有相同的访问方式(如:O_RDONLY,O_RDWR,o_WRONLY)
        新文件描述符将共享文件状态标记
        新文件将在exec标记上关闭开关,意思是新文件描述符将保持交叉执行调用????(The new file will have the close on exec flag turned off. That means the new file descriptor will remain open across exec calls)

论坛徽章:
0
83 [报告]
发表于 2006-02-16 17:14 |只看该作者
原帖由 horseman 于 2006-2-16 17:02 发表
*** 翻译的很不好,请多多包含,后面的章节将会继续,请大家一起校验,多谢了先 ***


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

一般来 ...



辛苦辛苦!

最好把文章中列举的源代码用“插入代码”功能框起来,这样便于阅读。

论坛徽章:
0
84 [报告]
发表于 2006-02-16 17:34 |只看该作者
it means a text file you edit has the same programmatic interface as a modem, printer, or network card。
我觉得这句是:这意味着你编辑的一个文本文件一样可以作为调制解调器,打印机或网卡的程序接口。

[ 本帖最后由 孙轩 于 2006-2-16 17:36 编辑 ]

论坛徽章:
0
85 [报告]
发表于 2006-02-16 17:46 |只看该作者
The new file will have the close on exec flag turned off. That means the new file descriptor will remain open across exec calls

我觉得是:这个新文件将在运行标志关闭时关闭。也就是说这个新文件描述符将在运行调用时保持打开。

论坛徽章:
0
86 [报告]
发表于 2006-02-16 17:48 |只看该作者
原帖由 孙轩 于 2006-2-16 17:34 发表
it means a text file you edit has the same programmatic interface as a modem, printer, or network card。
我觉得这句是:这意味着你编辑的一个文本文件一样可以作为调制解调器,打印机或网卡的程序接口。


应该不是的。作者在这里是想说,正是由于Unix把一切都当成一个文件,所以“外围设备文件”和“文本文件”的“编程接口”是相同的。它们都可以“write”或者“read”。

所以这句话的意思我觉得应该是:这就意味着你所编辑的文本文件具有和调制解调器、打印机或网卡相同的编程接口。

论坛徽章:
0
87 [报告]
发表于 2006-02-16 18:30 |只看该作者
原帖由 孙轩 于 2006-2-16 17:46 发表
The new file will have the close on exec flag turned off. That means the new file descriptor will remain open across exec calls

我觉得是:这个新文件将在运行标志关闭时关闭。也就是说这个新文件描述符将在运行调用时保持打开。


“close on exec”是文件的一个标志,如果设置了这个标志,那么在执行exec系统调用的时候,
对应的文件描述符就会关闭。

事实上,当父进程派生(fork系统调用)出子进程的时候,子进程会把父进程的文件描述符都继承过来。
为了使子进程开始运行,还需要进行exec系统调用,上面说的意思就是在这个exec系统调用之后,刚继承
过来的那些文件描述符是继续保持在打开状态还是关闭。

所以,单看这句话的意思就是新文件的“close on exec”标志将被关闭,也即新的文件描述符在exec调用
之后仍将保持打开。

论坛徽章:
0
88 [报告]
发表于 2006-02-16 18:42 |只看该作者
原帖由 szjungle 于 2006-2-16 16:39 发表


都可以,汉语中意会的东西太多了


:wink::wink::wink:

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
89 [报告]
发表于 2006-02-16 19:10 |只看该作者
(接56楼)

  1. #define SIGALRM         14      /* alarm clock */
复制代码

在进程的计时器到期的时候,SIGALRM信号会被交付(delivered)给进程。这些计时器由本章后面将会提及的setitimer和alarm调用设置。缺省行为是终止进程。
  1. #define SIGTERM         15      /* software termination signal from kill */
复制代码

SIGTERM信号被发送给进程,通知该进程是时候终止了,并且在终止之前做一些清理活动。SIGTERM信号是Unix的kill命令发送的缺省信号,同时也是操作系统关闭时向进程发送的缺省信号。缺省行为是终止进程。
  1. #define SIGURG          16      /* urgent condition on IO channel */
复制代码

在进程已打开的套接字上发生某些情况时,SIGURG将被发送给该进程。如果进程不捕获这个信号的话,那么将被丢弃。缺省行为是丢弃这个信号。
  1. #define SIGSTOP         17      /* sendable stop signal not from tty */
复制代码

本信号不能被捕获或忽略。一旦进程接收到SIGSTOP信号,它会立即停止(stop),直到接收到另一个SIGCONT信号为止。缺省行为是停止进程,直到接收到一个SIGCONT信号为止。
  1. #define SIGTSTP         18      /* stop signal from tty */
复制代码

SIGSTP与SIGSTOP类似,它们的区别在于SIGSTP信号可以被捕获或忽略。当shell从键盘接收到CTRL-Z的时候就会交付(deliver)这个信号给进程。缺省行为是停止进程,直到接收到一个SIGCONT信号为止。
  1. #define SIGCONT         19      /* continue a stopped process */
复制代码

SIGCONT也是一个有意思的信号。如前所述,当进程停止的时候,这个信号用来告诉进程恢复运行。该信号的有趣的地方在于:它不能被忽略或阻塞,但可以被捕获。这样做很有意义:因为进程大概不愿意忽略或阻塞SIGCONT信号,否则,如果进程接收到SIGSTOP或SIGSTP的时候该怎么办?缺省行为是丢弃该信号。
  1. #define SIGCHLD         20      /* to parent on child stop or exit */
复制代码

SIGCHLD是由Berkeley Unix引入的,并且比SRV 4 Unix上的实现有更好的接口。(如果信号是一个没有追溯能力的过程(not a retroactive process),那么BSD的SIGCHID信号实现会比较好。在system V Unix的实现中,如果进程要求捕获该信号,操作系统会检查是否存在有任何未完成的子进程(这些子进程是已经退出(exit)的子进程,并且在等待调用wait的父进程收集它们的状态)。如果子进程退出的时候附带有一些终止信息(terminating information),那么信号处理句柄就会被调用。所以,仅仅要求捕获这个信号会导致信号处理句柄被调用(译注:即是上面说的“信号的追溯能力”),而这是却一种相当混乱的状况。)

一旦一个进程的子进程状态发生改变,SIGCHLD信号就会被发送给该进程。就像我在前面章节提到的,父进程虽然可以fork出子进程,但没有必要等待子进程退出。一般来说这是不太好的,因为这样的话,一旦进程退出就可能会变成一个僵尸进程。可是如果父进程捕获SIGCHLD信号的话,它就可以使用wait系列调用中的某一个去收集子进程状态,或者判断发生了什么事情。当发送SIGSTOP,SIGSTP或SIGCONF信号给子进程时,SIGCHLD信号也会被发送给父进程。缺省行为是丢弃该信号。
  1. #define SIGTTIN         21      /* to readers pgrp upon background tty read */
复制代码

当一个后台进程尝试进行一个读操作时,SIGTTIN信号被发送给该进程。进程将会阻塞直到接收到SIGCONT信号为止。缺省行为是停止进程,直到接收到SIGCONT信号。
  1. #define SIGTTOU         22      /* like TTIN if (tp->t_local&LTOSTOP) */
复制代码

SIGTTOU信号与SIGTTIN很相似,不同之处在于SIGTTOU信号是由于后台进程尝试对一个设置了TOSTOP属性的tty执行写操作时才会产生。然而,如果tty没有设置这个属性,SIGTTOU就不会被发送。缺省行为是停止进程,直到接收到SIGCONT信号。
  1. #define SIGIO           23      /* input/output possible signal */
复制代码

如果进程在一个文件描述符上有I/O操作的话,SIGIO信号将被发送给这个进程。进程可以通过fcntl调用来设置。缺省行为是丢弃该信号。
  1. #define SIGXCPU         24      /* exceeded CPU time limit */
复制代码

如果一旦进程超出了它可以使用的CPU限制(CPU limit),SIGXCPU信号就被发送给它。这个限制可以使用随后讨论的setrlimit设置。缺省行为是终止进程。
  1. #define SIGXFSZ         25      /* exceeded file size limit */
复制代码
如果一旦进程超出了它可以使用的文件大小限制,SIGXFSZ信号就被发送给它。稍后我们会继续讨论这个信号。缺省行为是终止进程。
  1. #define SIGVTALRM       26      /* virtual time alarm */
复制代码

如果一旦进程超过了它设定的虚拟计时器计数时,SIGVTALRM信号就被发送给它。缺省行为是终止进程。
  1. #define SIGPROF         27      /* profiling time alarm */
复制代码

当设置了计时器时,SIGPROF是另一个将会发送给进程的信号。缺省行为是终止进程。
  1. #define SIGWINCH        28      /* window size changes */
复制代码

当进程调整了终端的行或列时(比如增大你的xterm的尺寸),SIGWINCH信号被发送给该进程。缺省行为是丢弃该信号。
  1. #define SIGUSR1         29      /* user defined signal 1 */
  2. #define SIGUSR2         30      /* user defined signal 2 */
复制代码

SIGUSR1和SIGUSR2这两个信号被设计为用户指定。它们可以被设定来完成你的任何需要。换句话说,操作系统没有任何行为与这两个信号关联。缺省行为是终止进程。(译注:按原文的意思翻译出来似乎这两句话有点矛盾。)

[size=-1]4.3 系统调用
那么,你该如何使用信号呢?有时候甚至拿不准是否应该使用信号。例如,当信号被交付的时候,一方面你可以在行为发生之前,分析当前情况,找出信号发生的原因,或者找到这些信号是从哪里发出来的;另一方面,其他一些时候你也可以只是希望简单的退出程序,并且在清除之后创建一个核心转储文件。参见最后部分的简单代码可以获得这些函数的较详细的例子。

Kill函数
kill函数对于那些经常在命令行使用kill命令杀死进程的人来说是再熟悉不过的。基本语法是:
  
  1. int   kill(pid_t pid, int sig);
复制代码

Kill函数将指定的信号发送给进程号为pid的进程。只有当进程符合下面几点情况的时候信号才会被交付:
• 发送与接收进程有相同的有效用户ID(UID);
• 发送进程有适当的权限(例如:setuid命令);
• 发送进程有超级用户(root)的UID。

注意:SIGCONT信号是一个特例,它可以由当前进程发送给任何一个该进程的派生进程。

使用不同的调用参数使得kill函数的行为差别非常大。这些行为如下所述:
(译注:下面的PID应该指的是上面kill函数原型中的那个pid,我在这里做出说明并保留原文)
• 如果PID大于0,并且发送进程有适当的权限,那么参数sig指定的信号将被交付。
• 如果PID等于0,那么sig信号将被交付给所有那些与发送进程有相同组ID的进程。(发送进程同样需要满足权限需求。)
• 如果PID是 -1,那么信号将被发送给所有那些与发送进程有相同有效用户ID的进程(不包含发送进程在内)。然而,如果发送进程的有效用户ID与超级用户(root)的相同,那么信号被交付给除了系统进程(由它们的proc结构中的p_flag域是否是P_SYSTEM来定义)之外的所有进程。在这个特殊的例子中,如果某些进程不能被发送(could not be sent)sig信号,kill函数并不返回一个错误。
• 如果sig是0,kill函数只检查错误(例如,无效权限,不存在的进程等)。该用法有时候用来检查一个指定进程是否存在。
• 如果成功的话kill函数返回0,否则返回-1。kill调用失败时会在errno全局变量中设置相应的错误值。


kill的另一个版本是raise函数:
   
  1. int    raise(int sig);
复制代码

raise函数会向当前进程发送sig信号。该函数用处不是很大,因为它只能够给当前进程发送信号。raise函数调用成功时返回0,否则返回-1。调用失败时会在errno全局变量中设置相应的错误值,效果和signal函数的返回类似:(译注:原文只有两个单词“as in:”,我并不知道作者把signal列在这里所要表达的意思,所以我按照我的理解+猜测来翻译的。如果大家有什么建议,或是需要纠正的话,请一定告诉我。)
  
  1. void (*signal(int sig, void (*func)(int)))(int);
复制代码


(to be continued. about 50%)

[ 本帖最后由 gvim 于 2006-2-16 19:14 编辑 ]

论坛徽章:
0
90 [报告]
发表于 2006-02-16 19:18 |只看该作者
原帖由 gvim 于 2006-2-16 19:10 发表
(接56楼)

  1. #define SIGALRM         14      /* alarm clock */
复制代码

在进程的计时器到期的时候,SIGALRM信号会被交付(delivered)给进程。这些计时器由本章后面将会提及的setitimer和alarm调用设置 ...


给你整过去了!进度条也已更新,
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP