01 2014 档案

摘要:就像线程具有属性一样,线程的同步对象(如互斥量、读写锁、条件变量、自旋锁和屏障)也有属性。http://www.cnblogs.com/nufangrensheng/p/3521654.html中介绍了自旋锁的唯一的一个属性,本篇介绍互斥量、读写锁、条件变量及屏障的属性。 1、互斥量属性 用pthread_mutexattr_init初始化pthread_mutexattr_t结构,用pthr... 阅读全文
posted @ 2014-01-17 10:30 ITtecman 阅读(1317) 评论(0) 推荐(0) 编辑
摘要:http://www.cnblogs.com/nufangrensheng/p/3518411.html中介绍了pthread_create函数,并且当时的例子中,传入的参数都是空指针,而不是指向pthread_attr_t结构的指针。可以使用pthread_attr_t结构修改线程默认属性,并把这些属性与创建的线程联系起来。可以使用pthread_attr_init函数初始化pthread_at... 阅读全文
posted @ 2014-01-16 15:17 ITtecman 阅读(2481) 评论(0) 推荐(1) 编辑
摘要:在http://www.cnblogs.com/nufangrensheng/p/3496323.html中讨论了sysconf函数,Single UNIX Specification定义了与线程操作有关的一些限制。与其他的系统限制一样,这些线程限制也可以通过sysconf函数进行查询。表12-1总结了这些限制。 表12-1 线程限制和sysconf的name参数 ... 阅读全文
posted @ 2014-01-16 15:15 ITtecman 阅读(1999) 评论(0) 推荐(0) 编辑
摘要:前言 当多个控制线程共享相同的内存时,需要确保每个线程看到一致的数据视图。如果每个线程使用的变量都是其他线程不会读取或修改的,那么就不会存在一致性问题。同样地,如果变量是只读的,多个线程同时读取该变量也不会有一致性问题。但是,当某个线程可以修改变量,而其他线程也可以读取或修改这个变量的时候,就需要对这些线程进行同步,以确保它们在访问变量的存储内容时不会访问到无效的数值。 当一个线程修改变量时,... 阅读全文
posted @ 2014-01-15 22:31 ITtecman 阅读(24644) 评论(1) 推荐(4) 编辑
摘要:如果进程中的任一线程调用了exit、_Exit或者_exit,那么整个进程就会终止。与此类似,如果信号的默认动作是终止进程,那么,把该信号发送到线程会终止整个进程。 单个线程可以通过下列三种方式退出,在不终止整个进程的情况下停止它的控制流。 (1)线程只是从启动例程中返回,返回值是线程的退出码。 (2)线程可以被同一进程中的其他线程取消。 (3)线程调用pthread_exit。 ... 阅读全文
posted @ 2014-01-14 15:49 ITtecman 阅读(1876) 评论(0) 推荐(0) 编辑
摘要:在传统的UNIX进程模型中,每个进程只有一个控制线程。从概念上讲,这与基于线程的模型中只包含一个线程是相同的。在POSIX线程(pthread)的情况下,程序开始运行时,它也是以单进程中的单个控制线程启动的,在创建多个控制线程以前,程序的行为与传统的进程并没有什么区别。新增的线程可以通过调用pthread_create函数创建。#include int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*st... 阅读全文
posted @ 2014-01-14 09:37 ITtecman 阅读(1148) 评论(0) 推荐(0) 编辑
摘要:就像每个进程有一个进程ID一样,每个线程也有一个线程ID。进程ID在整个系统中是唯一的,但线程ID不同,线程ID只在它所属的进程环境中有效。 进程ID,用pid_t数据类型来表示,是一个非负整数。线程ID则用pthread_t数据类型来表示,实现的时候可以用一个结构来代表pthread_t数据类型,所以可移植的操作系统实现不能把它作为整数处理。因此必须使用函数来对两个线程ID进行比较。 ... 阅读全文
posted @ 2014-01-13 22:12 ITtecman 阅读(1902) 评论(0) 推荐(0) 编辑
摘要:典型的UNIX进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情。有了多个控制线程(或简称为线程)以后,在程序设计时可以把进程设计成在同一时刻能够做不止一件事,每个线程处理各自独立的任务。这种方法有很多好处: 通过为每种事件类型的处理分配单独的线程,能够简化处理异步事件的代码。每个线程在进行事件处理时可以采用同步编程模式,同步编程模式要比异步编程模式简单得多。 多个进程必须... 阅读全文
posted @ 2014-01-13 21:58 ITtecman 阅读(457) 评论(0) 推荐(0) 编辑
摘要:依赖于实现的信号的其他特征。 1、信号名字 某些系统提供数组 extern char *sys_siglist[]; 数组下标是信号编号,给出一个指向信号字符串名字的指针。 这些系统通常也提供函数psignal。 #include void psignal(int signo, const char * msg);字符串msg(通常是程序名)输出到标准出错文件,后接一个冒号和一个... 阅读全文
posted @ 2014-01-13 15:13 ITtecman 阅读(311) 评论(0) 推荐(0) 编辑
摘要:在表10-1(http://www.cnblogs.com/nufangrensheng/p/3514157.html)所示的信号中,POSIX.1认为有6个与作业控制有关: SIGCHLD 子进程已停止或终止。 SIGCONT 如果进程已停止,则使其继续运行。 SIGSTOP 停止信号(不能被捕捉或忽略)。 SIGTSTP 交互式停止信号。 SIGTT... 阅读全文
posted @ 2014-01-13 14:44 ITtecman 阅读(933) 评论(0) 推荐(0) 编辑
摘要:#include unsigned int sleep(unsigned int seconds);返回值:0或未休眠够的秒数此函数使调用进程被挂起,直到满足以下条件之一:(1)已经过了seconds所指定的墙上时钟时间。(2)调用进程捕捉到一个信号并从信号处理程序返回。如果alarm信号一样,由于其他系统活动,实际返回时间比所要求的会迟一些。在第(1)种情形中,返回值是0。当由于捕捉到某个... 阅读全文
posted @ 2014-01-13 14:14 ITtecman 阅读(1364) 评论(0) 推荐(0) 编辑
摘要:在http://www.cnblogs.com/nufangrensheng/p/3512291.html中已经有了一个system函数的实现,但是该版本并不执行任何信号处理。POSIX.1要求system忽略SIGINT和SIGQUIT,阻塞SIGCHLD。 实例 程序清单10-19使用http://www.cnblogs.com/nufangrensheng/p/3512291.html中... 阅读全文
posted @ 2014-01-13 11:22 ITtecman 阅读(1074) 评论(0) 推荐(0) 编辑
摘要:abort函数的功能是使异常程序终止。#include void abort(void);此函数不返回此函数将SIGABRT信号发送给调用进程(进程不应忽略此信号)。ISO C规定,调用abort将向主机环境递送一个未成功的终止通知,其方法是调用raise(SIGABRT)函数。实例程序清单10-18 abort的POSIX.1实现#include #include #include #include voidabort(void) /* POSIX-style abort() function */{ sigset_t mask; struct sigacti... 阅读全文
posted @ 2014-01-12 22:17 ITtecman 阅读(3200) 评论(1) 推荐(1) 编辑
摘要:更改进程的信号屏蔽字可以阻塞所选择的信号,或解除对它们的阻塞。使用这种技术可以保护不希望由信号中断的代码临界区。如果希望对一个信号解除阻塞,然后pause等待以前被阻塞的信号发生,则又将如何呢?假定信号时SIGINT,实现这一点的一种不正确的方法是: sigset_t newmask, oldmask;sigemptyset(&newmask);sigaddset(&newmask,... 阅读全文
posted @ 2014-01-12 18:29 ITtecman 阅读(7613) 评论(0) 推荐(1) 编辑
摘要:在信号处理程序中经常调用longjmp函数以返回到程序的主循环中,而不是从该处理程序返回。 但是,调用longjmp有一个问题。当捕捉到一个信号时,进入信号捕捉函数,此时当前信号被自动地加到进程的信号屏蔽字中。这阻止了后来产生的这种信号中断该信号处理程序。(仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值:http://www.cnblogs.com/nufangrensheng/p/3... 阅读全文
posted @ 2014-01-12 16:48 ITtecman 阅读(14106) 评论(4) 推荐(2) 编辑
摘要:sigaction函数的功能是检查或修改与指定信号相关联的处理动作(或同时执行这两种操作)。#include int sigaction( int signo, const struct sigaction *restrict act, struct sigaction *restrict oact);返回值:若成功则返回0,若出错则返回-1其中,参数signo是要检测或修改其具体动作的信号编号。若act指针非空,则要修改其动作。如果oact指针非空,则系统经由oact指针返回该信号的上一个动作。此函数使用下列结构:struct sigaction { void (*sa_hand... 阅读全文
posted @ 2014-01-12 14:43 ITtecman 阅读(15827) 评论(0) 推荐(2) 编辑
摘要:sigpending函数返回信号集,其中的各个信号对于调用进程是阻塞的而不能递送,因而也一定是当前未决的。该信号集通过set参数返回。(这些信号是已经产生的信号,但因为信号屏蔽字中对其设置了屏蔽位,从而被阻塞,不能递送给进程的那些信号。注意sigpending返回的信号集与信号屏蔽字的区别。从集合角度来讲,此信号集是当前信号屏蔽字的子集。) #include int sigpending(... 阅读全文
posted @ 2014-01-11 20:19 ITtecman 阅读(2085) 评论(0) 推荐(0) 编辑
摘要:一个进程的信号屏蔽字规定了当前阻塞而不能递送给该进程的信号集。调用函数sigprocmask可以检测或更改其信号屏蔽字,或者在一个步骤中同时执行这两个操作。 #include int sigprocmask( int how, const sigset_t *restrict set, sigset_t *restrict oset );返回值:若成功则返回0,若出错则返回-1首先,若os... 阅读全文
posted @ 2014-01-11 19:22 ITtecman 阅读(5205) 评论(0) 推荐(0) 编辑
摘要:我们需要有一个能表示多个信号——信号集(signal set)的数据类型。POSIX.1定义了数据类型sigset_t以包含一个信号集,并且定义了下列五个处理信号集的函数。 #include int sigemptyset(sigset_t *set);int sigfillset(sigset_t *set);int sigaddset(sigset_t *set, int signo)... 阅读全文
posted @ 2014-01-11 18:34 ITtecman 阅读(1154) 评论(0) 推荐(0) 编辑
摘要:一、不可靠的信号在早期的UNIX版本中,信号是不可靠的。不可靠在这里指的是,信号可能会丢失:一个信号发生了,但进程却可能一直不知道这一点。早期版本中的一个问题是在进程每次接到信号对其进行处理时,随即将该信号动作复位为默认值(经测试,发现我现在用的Red Hat Linux 2.6.18也是这样处理的。)。在描述这些早期系统的编程书籍中,有一个经典实例,它与如何处理中断信号相关,其代码与下面所示的相似:int sig_int(); /* my signal handling function */...signal(SIGINT, sig_int); /... 阅读全文
posted @ 2014-01-11 15:36 ITtecman 阅读(1282) 评论(0) 推荐(0) 编辑
摘要:使用alarm函数可以设置一个计时器,在将来某个指定的时间,该计时器会超时。当计时器超时时,产生SIGALRM信号。如果不忽略或不捕捉此信号,则其默认动作是终止调用该alarm函数的进程。 #include unsigned int alarm( unsigned int seconds );返回值:0或以前设置的闹钟时间的余留秒数其中,参数seconds的值是秒数,经过了指定的secon... 阅读全文
posted @ 2014-01-11 15:11 ITtecman 阅读(1586) 评论(0) 推荐(0) 编辑
摘要:kill函数将信号发送给进程或进程组。raise函数则允许进程向自身发送信号。 #include int kill(pid_t pid, int signo);int raise(int signo);两个函数返回值:若成功则返回0,若出错则返回-1调用 raise(signo);等价于调用 kill(getpid(), signo);kill的pid参数有4种不同的情况:pid > ... 阅读全文
posted @ 2014-01-11 11:11 ITtecman 阅读(1787) 评论(0) 推荐(0) 编辑
摘要:当引发信号的事件发生时,为进程产生一个信号(或向进程发送一个信号)。事件可以是硬件异常、软件条件、终端产生的信号或调用kill函数。 在产生了信号时,内核通常在进程表中设置一个某种形式的标志。当对信号采取了这种动作时,我们说向进程递送了一个信号。 在信号产生(generation)和递送(delivery)之间的时间间隔,称信号是未决的(pending)。 进程可以选用信号递送阻塞。如果为进... 阅读全文
posted @ 2014-01-11 10:10 ITtecman 阅读(622) 评论(0) 推荐(0) 编辑
摘要:进程捕捉到信号并对其进行处理时,进程正在执行的指令序列就被信号处理程序临时中断,它首先执行该信号处理程序中的指令。如果从信号处理程序返回(例如信号处理程序没有调用exit或longjmp),则继续执行在捕捉到信号时进程正在执行的正常指令序列。但在信号处理程序中,不能判断捕捉到信号时进程在何处执行。如果程序正在执行malloc,在其堆中分配另外的存储空间,而此时由于捕捉到信号而插入执行该信号处理程... 阅读全文
posted @ 2014-01-11 09:32 ITtecman 阅读(592) 评论(0) 推荐(1) 编辑
摘要:UNIX系统的信号机制最简单的接口是signal函数。signal函数的功能:为指定的信号安装一个新的信号处理函数。#include void (*signal(int signo, void (*func)(int)))(int);复杂原型分开看:void (*signal( int signo, void (*func)(int) ) )(int);函数名 :signal函数参数 :int signo, void (*func)(int)返回值类型:void (*)(int);signo参数是信号名(参见:http://www.cnblogs.com/nufangrensheng/p/35 阅读全文
posted @ 2014-01-10 22:16 ITtecman 阅读(18502) 评论(1) 推荐(1) 编辑
摘要:信号是软中断,它提供了一种处理异步事件的方法。 首先,每个信号都有一个名字。这些名字都以三个字符SIG开头。 在头文件中,这些信号都被定义为正整数(信号编号)。 实际上,实现将各信号定义在另一个头文件中,但是该头文件又包括在中。通常,若应用程序和内核两者都需使用同一定义,那么就将有关信息放置在内核头文件中,然后用户级头文件再包括该内核头文件。 不存在编号为0的信号。(kill函数对信号编号... 阅读全文
posted @ 2014-01-10 17:52 ITtecman 阅读(1729) 评论(0) 推荐(2) 编辑
摘要:一个其父进程已终止的进程称为孤儿进程(orphan process),这种进程由init进程“收养”。 整个进程组也可以成为“孤儿”。 孤儿进程组(orphan process group):该组中每个成员的父进程要么是该组中的一个成员,要么不是该组所属会话的成员。 对孤儿进程组的另一种描述:一个进程组不是孤儿进程组的条件是,该组中有一个进程,其父进程属于同一会话的另... 阅读全文
posted @ 2014-01-10 16:22 ITtecman 阅读(375) 评论(0) 推荐(1) 编辑
摘要:作业控制,它允许在一个终端上启动多个作业(进程组),它控制哪一个作业可以访问该终端,以及哪些作业在后台运行。作业控制要求下面三种形式的支持:(1)支持作业控制的shell。(2)内核中的终端驱动程序必须支持作业控制。(3)内核必须提供对某些作业控制信号的支持。从shell使用作业控制功能角度讲,用户可以在前台或后台启动一个作业。一个作业只是几个进程的集合,通常是一个进程的管道线。例如:vi main.c在前台启动了只有一个进程组成的一个作业。命令:pr *.c | lpr &make all &在后台启动了两个作业。这两个后台作业调用的所有进程都在后台运行。当启动一个后台作业时 阅读全文
posted @ 2014-01-10 15:05 ITtecman 阅读(775) 评论(0) 推荐(0) 编辑
摘要:需要有一种方法来通知内核哪一个进程组是前台进程组,这样,终端设备驱动程序就能了解将终端输入和终端产生的信号送到何处。#include pid_t tcgetpgrp( int filedes );返回值:若成功则返回前台进程组的进程组ID,若出错则返回-1int tcsetpgrp( int filedes, pid_t pgrpid );返回值:若成功则返回0,若出错则返回-1函数tcgetpgrp返回前台进程组的进程组ID,该前台进程组与在filedes上打开的终端相关联。如果进程有一个控制终端,则该进程可以调用tcsetpgrp将前台进程组ID设置为pgrpid。pgrpid的值应当是在 阅读全文
posted @ 2014-01-10 14:07 ITtecman 阅读(4399) 评论(0) 推荐(1) 编辑
摘要:会话和进程组有一些其他特性: 一个会话可以有一个控制终端(controlling terminal)。这通常是登录到其上的终端设备(在终端登录情况下)或伪终端设备(在网络登录情况下)。 建立与控制终端连接的会话首进程被称为控制进程(controlling process)。 一个会话中的几个进程组可被分成一个前台进程组(foreground process group)以及一个... 阅读全文
posted @ 2014-01-10 11:52 ITtecman 阅读(3047) 评论(0) 推荐(2) 编辑
摘要:会话(session)是一个或多个进程组的集合。 例如,可以具有图9-6中所示的安排。其中,在一个会话中有三个进程组。 图9-6 进程组和会话中的进程安排 通常是由shell的管道线将几个进程变成一组的。例如,图9-6中的安排可能是由下列形式的shell命令形成的: proc1 | proc2 & pro... 阅读全文
posted @ 2014-01-10 11:27 ITtecman 阅读(1675) 评论(0) 推荐(1) 编辑
摘要:每个进程除了有一个进程ID之外,还属于一个进程组。 进程组是一个或多个进程的集合。通常,它们与同一作业相关联,可以接收来自同一终端的各种信号。每个进程组有一个唯一的进程组ID。进程组ID类似于进程ID——它是一个正整数,并可存放在pid_t数据类型中。函数getpgrp返回调用进程的进程组ID。 #include pid_t getpgrp(void);返回值:调用进程的进程组ID在早期... 阅读全文
posted @ 2014-01-10 11:02 ITtecman 阅读(2126) 评论(0) 推荐(0) 编辑
摘要:通过串行终端登录至系统和经由网络登录至系统两者之间的主要(物理上的)区别是:通过网络登录时,终端和计算机之间的连接不是点对点连接。在这种情况下,login只是一种可用的服务,这与其他网络服务(例如FTP或SMTP)的性质相同。 在终端登录中,init知道哪些终端设备可用来进行登录,并为每个设备生成一个getty进程。但是在网络登录情况下,所有登录都经由内核的网络接口驱动程序(如以太网驱动程序),... 阅读全文
posted @ 2014-01-10 10:35 ITtecman 阅读(463) 评论(0) 推荐(0) 编辑
摘要:在早期的UNIX系统中,用户用哑终端(用硬连接连到主机,更多关于哑终端:http://zh.wikipedia.org/wiki/%E5%93%91%E7%BB%88%E7%AB%AF)进行登录。终端要么是本地的(直接连接)要么是远程的(通过调制解调器连接)。在这两种情况下,登录都经由内核中的终端设备驱动程序。1、BSD终端登录系统管理员创建通常名为/etc/ttys的文件,其中每个终端设备都有一行,每一行说明设备名和传递给getty程序的参数,例如,参数之一说明了终端的波特率等。当系统自举时,内核创建ID为1的进程,也就是init进程。init进程使系统进入多用户状态。init进程读文件/e 阅读全文
posted @ 2014-01-10 09:08 ITtecman 阅读(1094) 评论(0) 推荐(0) 编辑
摘要:任一进程都可调用times函数以获得它自己及已终止子进程的墙上时钟时间、用户CPU时间和系统CPU时间(关于这三种时间的含义可参考:http://www.cnblogs.com/nufangrensheng/p/3495526.html)。 #include clock_t times( struct tms *buf );返回值:若成功则返回流逝的墙上时钟时间(单位:时钟滴答数),若出错... 阅读全文
posted @ 2014-01-09 20:29 ITtecman 阅读(769) 评论(0) 推荐(0) 编辑
摘要:任一进程都可以得到其实际和有效用户ID及组ID。但是有时希望找到运行该程序的用户登录名。我们可以调用getpwuid(getuid()),但是如果一个用户有多个登录名,这些登录名又对应着同一个用户ID,那么又将如何呢?(一个人在口令文件中可以有多个登录项,它们的用户ID相同,但登录shell则不同。) 系统通常记录用户登录时使用的名字,用getlogin函数可以获取此登录名。 #inclu... 阅读全文
posted @ 2014-01-09 18:27 ITtecman 阅读(426) 评论(0) 推荐(0) 编辑
摘要:大多数UNIX系统提供了一个选项以进行进程会计(process accounting)处理。启用该选项后,每当进程结束时内核就写一个会计记录。典型的会计记录包含总量较小的二进制数据,一般包括命令名、所使用的CPU时间总量、用户ID和组ID、启动时间等。 函数(acct)用于启用和禁用进程会计。唯一使用这一函数的命令是accton(8)命令。超级用户(系统管理员)执行一个带路径名参数(如:/var... 阅读全文
posted @ 2014-01-09 18:13 ITtecman 阅读(1741) 评论(0) 推荐(0) 编辑
摘要:参考:http://news.newhua.com/news1/program_language/2010/623/10623141048745773199BCF0CFH6AKB9930IGCFKHBH4IBE65IDFI07F.html?lt=common 基本概念:1>tty(终端设备的统称):tty一词源于teletypes,或者teletypewriters,原来指的是电传打字机,是通过串行线用打印机键盘阅读和发送信息的东西,后来这东西被键盘与显示器取代,所以现在叫终端比较合适。终端是一种字符型设备,它有多种类型,通常使用tty来简称各种类型的终端设备。2>pty(伪终端, 阅读全文
posted @ 2014-01-09 17:23 ITtecman 阅读(1071) 评论(0) 推荐(0) 编辑
摘要:ISO C定义了system函数,但是其操作对系统的依赖性很强。POSIX.1包括了system接口,它扩展了ISO C定义,以描述system在POSIX.1环境中的运行行为。 #include int system( const char *cmdstring );如果cmdstring是一个空指针,则仅当命令处理程序可用时,system返回非0值,这一特征可以确定在一个给定的操作系统... 阅读全文
posted @ 2014-01-09 15:30 ITtecman 阅读(2880) 评论(0) 推荐(0) 编辑
摘要:所有现今的UNIX系统都支持解释器文件(interpreter file)(也可称为解释器脚本)。这种文件是文本文件,其起始行格式是:#! pathname [optional-argument]感叹号和pathname之间的空格是可选的。最常见的解释器文件以下列行开始:#!/bin/shpathname通常是绝对路径名,对它不进行什么特殊的处理(即不使用PATH进行路径搜索)。对这种文件的识别是由内核作为exec系统调用处理的一部分来完成的。内核调用exec函数的进程实际执行的并不是该解释器文件,而是该解释器文件第一行中pathname所指定的文件。一定要将解释器文件(文本文件,它以#!开头 阅读全文
posted @ 2014-01-09 10:33 ITtecman 阅读(1178) 评论(0) 推荐(0) 编辑
摘要:在UNIX系统中,特权(例如能改变当前日期的表示法以及访问控制(例如,能否读、写一特定文件))是基于用户ID和组ID的。当程序需要增加特权,或需要访问当前并不允许访问的资源时,我们需要更换自己的用户ID或组ID,使得新ID具有合适的特权或访问权限。与此类似,当程序需要降低其特权或阻止对某些资源的访问时,也需要更换用户ID或组ID,从而使新ID不具有相应特权或访问这些资源的能力。 一般而言,在设计... 阅读全文
posted @ 2014-01-08 19:18 ITtecman 阅读(1161) 评论(0) 推荐(0) 编辑
摘要:用fork函数创建子进程后,子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程执行的程序完全替换为新程序,而新程序则从其main函数开始执行。因为调用exec并不创建新进程,所以前后的进程ID并未改变。exec只是用一个全新的程序替换了当前进程的正文、数据、堆和栈段。 有6种不同的exec函数可供使用,它们常常被统称为exec函数。这些exec函数使得UNIX... 阅读全文
posted @ 2014-01-08 16:00 ITtecman 阅读(12292) 评论(0) 推荐(0) 编辑
摘要:当多个进程都企图对共享数据进行某种处理,而最后的结果又取决于进程运行的顺序时,则我们认为这发生了竞争条件(race condition)。如果在fork之后的某种逻辑显式或隐式地依赖于在fork之后是父进程先运行还是子进程先运行,那么fork函数就会是竞争条件活跃的滋生地。通常,我们不能预料哪一个进程先运行。即使知道哪一个进程先运行,那么在该进程开始运行后,所发生的事情也依赖于系统负载以及内核的调度算法。如果一个进程希望等待一个子进程终止,则它必须调用一种wait函数。如果一个进程要等待其父进程终止,则可使用下列形式的循环:while ( getppid() != 1 ) sleep( ... 阅读全文
posted @ 2014-01-08 11:19 ITtecman 阅读(2378) 评论(0) 推荐(2) 编辑
摘要:大多数UNIX系统实现提供了另外两个函数wait3和wait4。它们提供的功能比POSIX.1函数wait、waitpid和waitid所提供的功能要多一个,这与附加参数rusage有关。该参数要求内核返回由终止进程及其所有子进程使用的资源汇总。 #include #include #include #include pid_t wait3( int *statloc, int optio... 阅读全文
posted @ 2014-01-08 10:11 ITtecman 阅读(1134) 评论(0) 推荐(0) 编辑
摘要:Single UNIX Specification的XSI扩展包括了另一个取进程终止状态的函数——waitid,此函数类似于waitpid,但提供了更多的灵活性。 #include int waitid( idtype_t idtype, id_t id, siginfo_t *infop, int options );返回值:若成功则返回0,若出错则返回-1与waitpid相似,wait... 阅读全文
posted @ 2014-01-08 09:56 ITtecman 阅读(2319) 评论(0) 推荐(0) 编辑
摘要:当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号。因为子进程终止是个异步事件(这可以在父进程运行的任何时候发生),所以这种信号也是内核向父进程发的异步通知。父进程可以选择忽略该信号,或者提供一个该信号发生时即被调用执行的函数(信号处理程序)。对于这种信号的系统默认动作是忽略它)。 调用wait或waitpid的进程可能会发生的情况: 如果其所有子进程都还在运行,则阻塞。... 阅读全文
posted @ 2014-01-08 09:39 ITtecman 阅读(3292) 评论(0) 推荐(0) 编辑
摘要:进程有下面5种正常终止方式:(1)在main函数内执行return语句。这等效于调用exit。(2)调用exit函数。此函数有ISO C定义,其操作包括调用各终止处理程序(终止处理程序在调用atexit函数时登记),然后关闭所有标准I/O流等。(3)调用_exit或_Exit函数。ISO C定义_Exit,其目的是为进程提供一种无需运行终止处理程序或信号处理程序而终止的方法。对标准I/O流是否进行冲洗,这取决于实现。在UNIX系统中,_Exit和_exit是同义的,并不清洗标准I/O流。_exit函数由exit调用,它处理UNIX特定的细节。在大多数UNIX系统实现中,exit(3)是标准C库 阅读全文
posted @ 2014-01-07 21:45 ITtecman 阅读(2743) 评论(0) 推荐(0) 编辑
摘要:vfork函数的调用序列和返回值与fork相同,但两者的语义不同。vfork用于创建一个新进程,而新进程的目的是exec一个新程序。vfork和fork一样都创建一个子进程,但是它并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec(或exit),于是也就不会存访该地址空间。相反,在子进程调用exec或exit之前,它在父进程的空间中运行。vfork和fork之间的另一个区别是:vfork保证子进程先运行,在它调用exec或exit之后父进程才可能被调度运行。(如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。)程序清单8-2 vfork函数实例[root 阅读全文
posted @ 2014-01-07 20:56 ITtecman 阅读(809) 评论(0) 推荐(0) 编辑
摘要:一个现有进程可以调用fork函数创建一个新进程。#include pid_t fork( void );返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1由fork创建的新进程被称为子进程(child process)。fork函数被调用一次,但返回两次。两次返回的唯一区别是子进程的返回值是0,而父进程的返回值则是新子进程的进程ID。将子进程ID返回给父进程的理由是:因为一个进程的子进程可以有多个,并且没有一个函数使一个进程可以获得其所有子进程的进程ID。fork使子进程得到返回值0的理由是:一个进程只会有一个父进程,所以子进程总是可以调用getppid以获得其父进程的进程ID(进程 阅读全文
posted @ 2014-01-07 20:14 ITtecman 阅读(5399) 评论(0) 推荐(0) 编辑
摘要:每个进程都有一个非负整型表示的唯一进程ID。因为进程ID标识符总是唯一的,常将其用作其他标识符的一部分以保证其唯一性。例如,应用程序有时就把进程ID作为名字的一部分来创建一个唯一的文件名。 虽然是唯一的,但是进程ID可以重用。当一个进程终止后,其进程ID就可以再次使用了。大多数UNIX系统实现延迟重用算法,使得赋予新建进程的ID不同于最近终止进程所使用的ID。这防止了将新进程误认为是使用同一ID... 阅读全文
posted @ 2014-01-07 17:58 ITtecman 阅读(2911) 评论(0) 推荐(0) 编辑
摘要:每个进程都有一组资源限制,其中一些可以用getrlimit和setrlimit函数查询和更改。 #include int getrlimit( int resource, struct rlimit *rlptr );int setrlimit( int resource, const struct rlimit *rlptr );两个函数返回值:若成功则返回0,若出错则返回非0值进程的资... 阅读全文
posted @ 2014-01-07 17:15 ITtecman 阅读(10856) 评论(0) 推荐(1) 编辑
摘要:在C中,goto语句是不能跨越函数的,而执行这样跳转功能的是函数setjmp和longjmp。这两个函数对于处理发生在深层嵌套函数调用中的出错情况是非常有用的。 setjmp和longjmp函数也称为非局部goto,非局部指的是,这不是由普通C语言goto语句在一个函数内实施的跳转,而是在栈上跳过若干调用帧,返回到当前函数调用路径上的某一函数中。 #include int setjmp(... 阅读全文
posted @ 2014-01-07 15:44 ITtecman 阅读(705) 评论(0) 推荐(0) 编辑
摘要:环境字符串的形式通常如下: name=value UNIX内核并不查看这些字符串,它们的解释完全取决于各个应用程序。 ISO C定义了一个函数getenv,可以用于取环境变量值,但是该标准又称环境变量的内容是由实现定义的。 #include char *getenv( const char *name );返回值:指向与name关联的value的指针,若未找到则返回NULL注意,... 阅读全文
posted @ 2014-01-07 10:25 ITtecman 阅读(2261) 评论(0) 推荐(0) 编辑
摘要:ISO C说明了三个用于存储器空间动态分配的函数: (1)malloc。分配指定字节数的存储区。此存储区中的初始值不确定。 (2)calloc。为指定数量具有指定长度的对象分配存储空间。该空间中的每一位都初始化为0。 (3)realloc。更改以前分配区的长度(增加或减少)。当增加长度时,可能需要将以前分配区的内容移到另一个足够大的区域,以便在尾端提供增加的存储区(此时,返回新分配区的指针,... 阅读全文
posted @ 2014-01-07 10:04 ITtecman 阅读(367) 评论(0) 推荐(0) 编辑
摘要:现在,大多数UNIX系统支持共享库。共享库使得可执行文件中不再需要包含公用的库例程,而只需在所有进程都可引用的存储区中维护这种库例程的一个副本。程序第一次执行或者第一次调用某个库函数时,用动态链接方法将程序与共享库函数相链接。这减少了每个可执行文件的长度,但增加了一些运行时间开销。这种时间开销发生在该程序第一次被执行时,或者每个共享库函数第一次被调用时。共享库的另一个优点是可以用库函数的新版本替代老版本,而无需对使用该库的程序重新连接编辑。(假定参数的数目和类型都没有发生改变。)在不同的系统中,程序可能使用不同的方法说明是否要使用共享库。比较典型的有cc(1)和ld(1)命令的选项。作为长度方 阅读全文
posted @ 2014-01-07 09:13 ITtecman 阅读(920) 评论(0) 推荐(0) 编辑
摘要:从历史上讲,C程序一直由下面几部分组成:正文段。这是由CPU执行的机器指令部分。通常,正文段是可共享的,所以即使是频繁执行的程序(如文本编辑器、C编译器和shell等)在存储器中也只需有一个副本,另外,正文段常常是只读的,以防止程序由于意外而修改其自身的指令。初始化数据段。(所有带有初始值的全局变量)通常将此段称为数据段,它包含了程序中需明确地赋初值的变量。例如,C程序中出现在任何函数之外的声明:int maxcount = 99;使此变量带有其初值存放在初始化数据段中。非初始化数据段。(所有未带初始值的全局变量)通常将此段称为bss段,这一名称来源于一个早期的汇编运算符,意思是“block 阅读全文
posted @ 2014-01-07 09:00 ITtecman 阅读(960) 评论(0) 推荐(0) 编辑
摘要:每个程序都会接收到一张环境表。与参数表一样,环境表也是一个字符指针数组,其中每个指针包含一个以null结束的C字符串的地址。全局变量environ则包含了该指针数组的地址:extern char **environ; 要在程序中使用全局变量environ时,需要用该语句作变量声明。extern指示environ在其他文件中已定义,要在本文件中使用。例如,如果该环境包含5个字符串,那么它看起来可能如图7-2所示。其中,每个字符串的结尾处都显示地有一个null字符。我们称environ为环境指针(environment pointer),指针数组为环境表,其中各指针指向的字符串为环境字符串。... 阅读全文
posted @ 2014-01-06 22:22 ITtecman 阅读(818) 评论(0) 推荐(0) 编辑
摘要:当执行一个程序时,调用exec的进程可将命令行参数传递给该新进程。这是UNIX shell的一部分常规操作。 程序清单7-3 将所有命令行参数回送到标准输出 [root@localhost apue]# cat prog7-3.c#include "apue.h"intmain(int argc, char *argv[]){ int i; for(i=0; ... 阅读全文
posted @ 2014-01-06 22:08 ITtecman 阅读(627) 评论(0) 推荐(0) 编辑
摘要:有8种方式使进程终止(termination),其中5种为正常终止,它们是:(1)从main返回。(2)调用exit。(3)调用_exit或_Exit。(4)最后一个线程从其启动例程返回。(5)最后一个线程调用pthread_exit。异常终止有3种方式,它们是:(6)调用abort。(7)接到一个信号并终止。(8)最后一个线程对取消请求作出响应。启动例程是这样编写的,使得从main返回后立即调用exit函数。(关于启动例程:http://learn.akae.cn/media/ch19s02.html)。如果将启动例程以C代码形式表示(实际上该例程常常用汇编语言编写),则它调用main函数的 阅读全文
posted @ 2014-01-06 21:45 ITtecman 阅读(902) 评论(0) 推荐(0) 编辑
摘要:C程序总是从main函数开始执行。main函数的原型是:int main( int argc, char *argv[] );其中,argc是命令行参数的数目,argv是指向参数的各个指针所构成的数组。当内核执行C程序时(使用一个exec函数),在调用main前先调用一个特殊的启动例程。可执行程序文件将此启动例程指定为程序的起始地址——这是由连接编辑器设置的,而连接编辑器则由C编译器(通常是cc)调用。启动例程从内核取得命令行参数和环境变量值,然后为按上述方式调用main函数做好安排。本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www 阅读全文
posted @ 2014-01-06 19:24 ITtecman 阅读(797) 评论(0) 推荐(0) 编辑
摘要:由UNIX内核提供的基本时间服务是计算自国际标准时间公元1970年1月1日00:00:00以来经过的秒数。这种秒数是以数据类型time_t表示的。我们称它们为日历时间。日历时间包括时间和日期。UNIX在这方面与其他操作系统的区别是:(a)以国际标准时间而非本地时间计时;(b)可自动进行转换,例如变换到夏时制;(c)将时间和日期作为一个量值保存。time函数返回当前时间和日期:#include time_t time( time_t *calptr );返回值:若成功则返回时间值,若出错则返回-1时间值总是作为函数值返回。如果参数不为空,则时间值也存放在由calptr指向的单元内。在系统V派生的 阅读全文
posted @ 2014-01-06 18:21 ITtecman 阅读(704) 评论(0) 推荐(0) 编辑
摘要:POSIX.1定义了uname函数,它返回与当前主机和操作系统有关的信息。 #include int uname( struct utsname *name );返回值:若成功则返回非负值,若出错则返回-1通过该函数的参数向其传递一个utsname结构的地址,然后该函数填写此结构。POSIX.1只定义了该结构中至少需要提供的字段(它们都是字符数组),而每个数组的长度则由实现确定。某些实现在... 阅读全文
posted @ 2014-01-06 17:12 ITtecman 阅读(381) 评论(0) 推荐(0) 编辑
摘要:大多数UNIX系统都提供下列两个数据文件:utmp文件,它记录当前登录进系统的各个用户;wtmp文件,它跟踪各个登录和注销事件。在V7中,每次写入这两个文件中的是包含下列结构的一条二进制记录: struct utmp { char ut_line[8]; /* tty line: "ttyh0", "ttyd0", "ttyp0", ... */ char ut_name... 阅读全文
posted @ 2014-01-06 16:48 ITtecman 阅读(397) 评论(0) 推荐(0) 编辑
摘要:在日常操作中,UNIX系统还使用很多其他文件。例如,BSD网络软件有一个记录各网络服务器所提供服务的数据文件(/etc/services),有一个记录协议信息的数据文件(/etc/protocols),还有一个则是记录网络信息的数据文件(/etc/networks)。 一般情况下,对于每个数据文件至少有三个函数: (1)get函数:读下一个记录,如果需要,还可以打开该文件。这些函数通常返回指向... 阅读全文
posted @ 2014-01-06 16:37 ITtecman 阅读(448) 评论(0) 推荐(0) 编辑
摘要:4.2BSD引入了附加组ID(supplementary group ID)的概念。我们不仅可以属于口令文件记录项中组ID所对应的组,也可属于多达16个另外的组。文件访问权限检查相应被修改为:不仅将进程的有效组ID与文件的组ID相比较,而且也将所有附加组ID与文件的组ID进行比较。 常量NGROUPS_MAX规定了附加组ID的数量,其常用值是16. 使用附加组ID的优点是不必再显式地经常更改组... 阅读全文
posted @ 2014-01-06 16:20 ITtecman 阅读(754) 评论(0) 推荐(0) 编辑
摘要:UNIX组文件(POSIX.1称其为组数据库)包含了表6-3中所示的字段。这些字段包含在中所定义的group结构中。 表6-3 /etc/group文件中的字段 字段gr_mem是一个指针数组,其中每个指针各指向一个属于该组的用户名。该数组以空指针结尾。 可以用下列... 阅读全文
posted @ 2014-01-06 15:53 ITtecman 阅读(255) 评论(0) 推荐(0) 编辑
摘要:加密口令是经单向加密算法处理过的用户口令副本。因为此算法是单向的,所以不能从加密口令猜测到原来的口令。 历史上使用的算法总是从64字符集中产生13个可打印字符。某些较新的系统使用MD5算法对口令加密,为每个加密口令产生31个字符。 给出一个加密口令,找不到一种算法可以将其逆转到普通文本口令(普通文本口令是在Password:提示符后键入的口令)。但是可以对口令进行猜测,将猜测的口令经单向算法变... 阅读全文
posted @ 2014-01-06 11:18 ITtecman 阅读(569) 评论(0) 推荐(0) 编辑
摘要:UNIX系统的口令文件(POSIX.1则将其称为用户数据库)包含了表6-1中所示的各字段,这些字段包含在中定义的passwd结构中。注意,POSIX.1只指定了passwd结构包含的10个字段中的5个。大多数平台至少支持其中7个字段。 表6-1 /etc/passwd文件中的字段由于历史原因,口令文件存储在/etc/passwd中,而且是一个ASCII文件。每一行包含6-1中所示的各字段,字段之间用冒号分隔。例如,在Linux上,该文件中可能有下列四行:root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x 阅读全文
posted @ 2014-01-06 10:57 ITtecman 阅读(562) 评论(0) 推荐(0) 编辑
摘要:5.4 下面的代码在一些机器上运行正确,而在另外一些机器运行时出错,解释问题所在?#include int main( void ){ char c; while( ( c = getchar() ) != EOF ) putchar( c );}答:这是一个比较常见的错误。getc以及getchar的返回值是整型,而不是字符型。由于EOF经常定义为-1,那么如果系统使用的是有符号的字符类型,程序还可以正常工作。但如果使用的是无符号字符类型,那么返回的EOF被保存到字符c后将不再是-1,所以,程序会进入死循环。5.6 对标准I/O流如何使用fsync函数?答:... 阅读全文
posted @ 2014-01-06 09:17 ITtecman 阅读(224) 评论(0) 推荐(0) 编辑
摘要:标准I/O并不完善。标准I/O库的一个不足之处是效率不高,这与它需要复制的数据量有关。当使用每次一行函数fgets和fputs时,通常需要复制两次数据:一次是在内核和标准I/O缓冲之间(当调用read和write时),第二次是在标准I/O缓冲区和用户程序中的行缓冲区之间。替代版本fio:快速I/O库则避免了这一点,其方法是使读一行的函数返回指向该行的指针,而不是将该行复制到另一个缓冲区中。由于执行了这种更改,grep(1)实用程序的速度增加了两倍。替代版本sfio:这一软件包在速度上与fio相近,通常快于标准I/O库。sfio也提供了一些其他标准I/O库所没有的新特征:推广了I/O流,使其不仅 阅读全文
posted @ 2014-01-06 08:43 ITtecman 阅读(533) 评论(0) 推荐(0) 编辑
摘要:ISO C标准I/O库提供了两个函数以帮助创建临时文件。#include char *tmpnam( char *ptr );返回值:指向唯一路径名的指针FILE *tmpfile( void );返回值:若成功则返回文件指针,若出错则返回NULL若ptr是NULL,则所产生的路径名存放在一个静态区中,指向该静态区的指针作为函数值返回。下一次调用tmpnam时,会重写该静态区(这意味着,如果我们调用此函数多次,而且想保存路径名,则我们应该保存该路径名的副本,而不是指针的副本)。如若ptr不是NULL,则认为它指向长度至少是L_tmpnam个字符的数组(常量L_tmpnam定义在头文件中)。所产 阅读全文
posted @ 2014-01-06 08:24 ITtecman 阅读(671) 评论(0) 推荐(0) 编辑
摘要:在UNIX系统中,标准I/O库最终都要调用文件I/O(read、write等)。每个标准I/O流都有一个与其相关联的文件描述符,可以对一个流调用fileno函数以获得其描述符。注意,fileno不是ISO C标准部分,而是POSIX.1支持的扩展。#include int fileno( FILE *fp );返回值:与该流相关联的文件描述符如果要调用dup或fcntl等函数,则需要此函数。为了了解你所使用的系统中标准I/O库的实现,最好从头文件开始。从中可以看到:FILE对象是如何定义的、每个流标志的定义以及定义为宏的各个标准I/O例程(例如getc)。程序清单5-3中的程序为三个标准流以及 阅读全文
posted @ 2014-01-05 20:31 ITtecman 阅读(602) 评论(0) 推荐(0) 编辑
摘要:本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。一、格式化输出执行格式化输出处理的是4个printf函数。#include int printf( const char *restrict format, ... );int fpritnf( FILE *restrict fp, const char *restrict fromat, ... );两个函数的返回值:若成功则返回输出字符数,若输出出错则返回负值int sprintf( char *restrict buf, const char *re 阅读全文
posted @ 2014-01-05 17:58 ITtecman 阅读(558) 评论(0) 推荐(0) 编辑
摘要:有三种方法定位标准I/O流。(1)ftell和fseek函数。这两个函数自V7以来就存在了,但是它们都假定文件的位置可以存放在一个长整型中。(2)ftello和fseeko函数。Single UNIX Specification引入了这两个函数,可以使文件偏移量不必一定使用长整型。它们使用off_t数据类型代替了长整型。(3)fgetpos和fsetpos函数。这两个函数是由ISO C引入的。它们使用一个抽象数据类型fpos_t记录文件的位置。这种数据类型可以定义为记录一个文件位置所需的长度。需要移植到非UNIX系统上运行的应用程序应当使用fgetpos和fsetpos。#include lo 阅读全文
posted @ 2014-01-05 15:18 ITtecman 阅读(1094) 评论(0) 推荐(0) 编辑
摘要:如果进行二进制I/O操作,那么我们更愿意一次读或写整个结构。因此,提供了下列两个函数以执行二进制I/O操作。#include size_t fread( void *restrict ptr, size_t size, size_t nobj, FILE *restrict fp );size_t fwrite( const void *restrict ptr, size_t size, size_t nobj, FILE *restrict fp );两个函数的返回值:读或写的对象数这些函数有两种常见的用法:(1)读或写一个二进制数组。例如,为了将一个浮点数组的第2-5个元素写至一个文件上 阅读全文
posted @ 2014-01-05 14:54 ITtecman 阅读(449) 评论(0) 推荐(0) 编辑
摘要:程序清单5-1 用getc和putc将标准输入复制到标准输出#include "apue.h"intmain( void ){ int c; while(( c = getc( stdin )) != EOF ) if( putc( c, stdout ) == EOF ) err_sys( "output error" ); if( ferror( stdin )) err_sys( "input error" ); exit( 0 );}程序清单5-2 用fgets和fputs将标准输入... 阅读全文
posted @ 2014-01-05 14:23 ITtecman 阅读(397) 评论(0) 推荐(0) 编辑
摘要:下面两个函数提供每次输入一行的功能。#include char *fgets( char *restrict buf, int n, FILE *restrict fp );char *gets( char *buf );两个函数返回值:若成功则返回buf,若已到达文件结尾或出错则返回NULL这两个函数都指定了缓冲区的地址,读入的行将送入其中。gets从标准输入读,而fgets则从指定的流读。对于fgets,必须指定缓冲区的长度n。此函数一直读到下一个换行符为止,但是不超过n-1个字符,读入的字符(包括换行符)被送入缓冲区。该缓冲区以null字符结尾。如若该行(包括最后一个换行符)的字符数超过 阅读全文
posted @ 2014-01-05 11:24 ITtecman 阅读(246) 评论(0) 推荐(0) 编辑
摘要:一旦打开了流,则可在三种不同类型的非格式化I/O中进行选择,对其进行读、写操作:(1)每次一个字符的I/O。一次读或写一个字符,如果流是带缓冲的,则标准I/O会处理所有缓冲。(2)每次一行的I/O。如果想要一次读或写一行,则使用fgets和fputs。每行都以一个换行符终止。当调用fgets时,应说明能处理的最大行长。(3)直接I/O。fread和fwrite函数支持这种类型的I/O。每次I/O操作读或写某种数量的对象,而每个对象具有指定的长度。这两个函数常用于从二进制文件中每次读或写一个结构。直接I/O(direct I/O)这个术语来自ISO C标准,有时也被称为二进制I/O、一次一个对象 阅读全文
posted @ 2014-01-05 09:26 ITtecman 阅读(436) 评论(0) 推荐(0) 编辑
摘要:下列三个函数打开一个标准I/O流。#include FILE *fopen( const char *restrict pathname, const char *restrict type );FILE *freopen( const char *restrict pathname, const char *restrict type, FILE *restrict fp );FILE *fdopen( int filedes, const char *type );三个函数的返回值:若成功则返回文件指针,若出错则返回NULL这三个函数的区别是:(1)fopen打开一个指定的文件。(2)fr 阅读全文
posted @ 2014-01-05 08:21 ITtecman 阅读(1111) 评论(3) 推荐(0) 编辑
摘要:标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数。它也对每个I/O流自动地进行缓冲管理,从而避免了应用程序需要考虑这一点所带来的麻烦。标准I/O提供了三种类型的缓冲:(1)全缓冲。这种情况下,在填满标准I/O缓冲区后才进行实际的I/O操作。对于驻留在磁盘上的文件通常是由标准I/O库实施全缓冲的。在一个流上执行第一次I/O操作时,相关标准I/O函数通常调用malloc获得需使用的缓冲区。术语冲洗(flush)说明标准I/O缓冲区的写操作。缓冲区可由标准I/O例程自动冲洗(例如当填满一个缓冲区时),或者可以调用函数fflush冲洗一个流。值得引起注意的是在UNIX环境中,f 阅读全文
posted @ 2014-01-04 21:20 ITtecman 阅读(662) 评论(0) 推荐(0) 编辑
摘要:对一个进程预定义了三个流,并且这三个流可以自动地被进程使用,它们是:标准输入、标准输出和标注出错。这些流引用的文件与文件描述符STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO所引用的文件相同。这三个标准I/O流通过预定义文件指针stdin、stdout和stderr加以引用。这三个文件指针同样定义在头文件中。本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。 阅读全文
posted @ 2014-01-04 20:16 ITtecman 阅读(287) 评论(0) 推荐(0) 编辑
摘要:对于标准I/O库,它们的操作是围绕流(stream)进行的。当用标准I/O库打开或创建一个文件时,我们已使一个流与一个文件相关联。对于ASCII字符集,一个字符用一个字节表示。对于国际字符集,一个字符可以用多个字节表示。标准I/O文件流可用于单字节或多字节(“宽”)字符集。流的定向(stream’s orientation)决定了所读、写的字符是单字节还是多字节。当一个流最初被创建时,它并没有定向。如若在未定向的流上使用一个多字节I/O函数(见),则将该流的定向设置为宽定向的。若在未定向的流上使用一个单字节I/O函数,则将该流的定向设置为字节定向的。只有两个函数可以改变流的定向。freopen 阅读全文
posted @ 2014-01-04 20:11 ITtecman 阅读(818) 评论(0) 推荐(0) 编辑
摘要:表4-12 文件访问权限位小结常量说明对普通文件的影响对目录的影响S_ISUID S_ISGID设置用户ID 设置组ID执行时设置有效用户ID 若组执行位设置,则执行时设置有效组ID,否则使强制性记录锁起作用(若支持)(不使用) 将在目录中创建的新文件的组ID设置为目录的组ID S_ISVTX粘住位在交换区保存程序正文(若支持)限制在目录中删除和更名文件 S_IRUSR S_IWUSR S_IXUSR用户读 用户写 用户执行许可用户读文件 ... 阅读全文
posted @ 2014-01-04 17:44 ITtecman 阅读(587) 评论(0) 推荐(0) 编辑
摘要:st_dev和st_rdev:每个文件系统所在的存储设备都由主、次设备号表示。设备号所用的数据类型是基本系统数据类型dev_t。主设备号标识设备驱动程序,有时编码为与其通信的外设板;次设备号标识特定的子设备。例如,磁盘驱动器经常包含若干个文件系统。在同一磁盘驱动器上的各文件系统通常具有相同的主设备号,但它们的次设备号却不同。我们通常可以使用两个宏,即major和minor来访问主、次设备号,大多数实现都定义了这两个宏。这就意味着我们无需关心这两个数是如何存放在dev_t对象中的。Linux将宏major和minor定义在头文件中,而该头文件又包括在中。系统中与每个文件名关联st_dev值是文件 阅读全文
posted @ 2014-01-04 17:31 ITtecman 阅读(1422) 评论(0) 推荐(0) 编辑
摘要:每个进程都有一个当前工作目录,此目录是搜索所有相对路径名的起点(不以斜杠开始的路径名为相对路径名)。当用户登录到UNIX系统时,其当前工作目录通常是口令文件(/etc/passwd)中该用户登录项的第6个字段——用户的起始目录(home directory)。当前工作目录是进程的一个属性,起始目录则是登录名的一个属性。进程通过调用chdir或fchdir函数可以更改当前工作目录。#include int chdir( const char *pathname );int fchdir( int filedes );两个函数的返回值:若成功则返回0,若出错则返回-1在这两个函数中,分别用path 阅读全文
posted @ 2014-01-04 16:39 ITtecman 阅读(2886) 评论(0) 推荐(0) 编辑
摘要:对某个目录具有访问权限的任一用户都可读该目录,但是,为了防止文件系统产生混乱,只有内核才能写目录。一个目录的写权限位和执行权限位决定了在该目录中能否创建新文件以及删除文件,它们并不表示能否写目录本身。#include DIR *opendir( const char *pathname );返回值:若成功则返回指针,若出错则返回NULLstruct dirent *readdir( DIR *dp );返回值:若成功则返回指针,若在目录结尾或出错则返回NULLvoid rewinddir( DIR *dp );int closedir( DIR *dp );返回值:若成功则返回0,若出错则返回 阅读全文
posted @ 2014-01-04 15:18 ITtecman 阅读(369) 评论(0) 推荐(0) 编辑
摘要:用mkdir函数创建目录,用rmdir函数删除目录。#include int mkdir( const char *pathname, mode_t mode );返回值:若成功则返回0,若出错则返回-1此函数创建一个新的空目录。其中,.和..目录项是自动创建的。所指定的文件访问权限mode由进程的文件模式创建屏蔽字修改。常见的错误时指定与文件相同的mode(只指定读、写权限)。但是,对于目录通常至少要设置1个执行权限位,以允许访问该目录中的文件名。用rmdir函数可以删除一个空目录。空目录是只包含.和..这两项的目录。#include int rmdir( const char *pathn 阅读全文
posted @ 2014-01-04 08:17 ITtecman 阅读(1570) 评论(0) 推荐(0) 编辑
摘要:对于这个算法,很多书上只是说一下思路,没有具体的实现。我在这里举个例子吧以4bit(计算方便一点,和16bit是一样的)做检验和来验证。 建设原始数据为 1100 , 1010 , 0000(校验位) 那么把他们按照4bit一组进行按位取反相加。 1100取反0011 , 1010取反是0101,0011加上0101 是1000,填入到校验位后 1100 , 1010 , 1000 那么这个就是要发送的数据。收到数据后同样进行按位取反相加。0011+0101+0111 =1111;全为1表示正确 另外注意,当地一步计算校验和的时候,有可能相加后最高位会有进位,那么不能舍弃,一定要加到低位,才能 阅读全文
posted @ 2014-01-03 19:56 ITtecman 阅读(1214) 评论(0) 推荐(1) 编辑
摘要:一个文件的访问和修改时间可以用utime函数更改。#include int utime( const char *pathname, const struct utimbuf *times );返回值:若成功则返回0,若出错则返回-1此函数所使用的数据结构是:struct utimbuf { time_t actime; /* access time */ time_t modtime; /* modification time */}此结构中的两个时间值是日历时间。这是自1970年1月1日00:00:00以来国际标准时间所经过的秒数。此函数的操作以及执行它所要求的特权... 阅读全文
posted @ 2014-01-03 16:38 ITtecman 阅读(3349) 评论(0) 推荐(0) 编辑
摘要:本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。对每个文件保持有三个时间字段,它们的意义见表4-10: 表4-10 与每个文件相关的三个时间值字段说明例子ls(1)选项st_atime文件数据的最后访问时间read-ust_mtime文件数据的最后修改时间write默认st_ctimei节点状态的最后更改时间chmod、chown-c注意修改时间(st_mtime)和更改状态时间(st_ctime)之间的区别。修改时间是文件内容最后一次被修改的时间。更改状态时间是该文件的i节点最后一次被修改的时间。很多 阅读全文
posted @ 2014-01-03 14:59 ITtecman 阅读(428) 评论(0) 推荐(0) 编辑
摘要:symlink函数创建一个符号链接。 #include int symlink( const char *actualpath, const char *sympath );返回值:若成功则返回0,若出错则返回-1该函数创建了一个指向actualpath的新目录项sympath,在创建此符号链接时,并不要求actualpath已经存在。并且,actualpath和sympath并不需要位于... 阅读全文
posted @ 2014-01-03 14:24 ITtecman 阅读(844) 评论(0) 推荐(0) 编辑
摘要:本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。符号链接是指向一个文件的间接指针,它与硬链接有所不同,硬链接直接指向文件的i节点。引入符号链接的原因是为了避开硬链接的一些限制:硬链接通常要求链接和文件位于同一文件系统中。只有超级用户才能创建指向目录的硬链接。对符号链接以及它指向何种对象并无任何文件系统限制,任何用户都可创建指向目录的符号链接。符号链接一般用于将一个文件或整个目录结构移到系统中的另一个位置。当使用以名字引用文件(而不是用打开文件的描述符引用文件)的函数时,应当了解该函数是否处理符号链接。也 阅读全文
posted @ 2014-01-03 14:14 ITtecman 阅读(2201) 评论(0) 推荐(0) 编辑
摘要:任何一个文件可以有多个目录项指向其i节点。创建一个指向现有文件的链接的方法是使用link函数。#include int link( const char *existingpath, const char *newpath );返回值:若成功返回0,若出错返回-1此函数创建一个新目录项newpath,它引用现有的文件existingpath。如若newpath已经存在,则返回出错。只创建newpath中的最后一个分量,路径中的其他部分应当已经存在。创建新目录项以及增加链接计数应当是个原子操作。虽然POSIX.1允许实现支持跨文件系统的链接,但是大多数实现要求这两个路径名在同一个文件系统中。如果 阅读全文
posted @ 2014-01-03 11:08 ITtecman 阅读(4329) 评论(0) 推荐(0) 编辑
摘要:我们可以把一个磁盘分成一个或多个分区。每个分区可以包含一个文件系统(见图4-1)。 图4-1 磁盘、分区和文件系统i节点(i-node)是固定长度的记录项,它包含有关文件的大部分信息。如果更仔细地观察一个柱面组的i节点和数据块部分,则可以看到图4-2中所示的情况。注意图4-2中的下列各点:在图中有两个目录项指向同一i节点。每个i节点中都有一个链接计数,其值是指向该i节点的目录项数。只有当链接计数减少至0时,才可删除该文件(也就是说可以释放该文件占用的数据块)。这就是为什么“解除对一个文件的链接”操作并不总是意味着“释放该文件占用的磁盘块”的原因。这也是为什么删除一个目录项的函数被称为unlin 阅读全文
posted @ 2014-01-03 09:22 ITtecman 阅读(674) 评论(0) 推荐(0) 编辑
摘要:有时我们需要在文件尾端截去一些数据以缩短文件。将一个文件清空为0是一个特例,在打开文件时使用O_TRUNC标志可以做到这一点。 #include int truncate( const char *pathname, off_t length );int ftruncate( int filedes, off_t length );两个函数的返回值:若成功则返回0, 若出错则返回-1这两个... 阅读全文
posted @ 2014-01-02 22:25 ITtecman 阅读(611) 评论(0) 推荐(0) 编辑
摘要:stat结构成员st_size表示以字节为单位的文件长度。此字段只对普通文件、目录文件和符号链接有意义。 对于普通文件,其文件长度可以是0,在读这种文件时,将得到文件结束(end-of-file)指示。 对于目录,文件长度通常是一个数(例如16或512)的倍数。 对于符号链接,文件长度是文件名中的实际字节数。例如: lrwxrwxrwx 1 root root 8 01-02 05:... 阅读全文
posted @ 2014-01-02 22:15 ITtecman 阅读(1215) 评论(0) 推荐(0) 编辑
摘要:下面几个chown函数可用于更改文件的用户ID和组ID。 #include int chown( const char *pathname, uid_t owner, gid_t group );int fchown( int filedes, uid_t owner, gid_t group );int lchown( const char *pathname, uid_t owner,... 阅读全文
posted @ 2014-01-02 21:38 ITtecman 阅读(3088) 评论(0) 推荐(0) 编辑
摘要:在UNIX尚未使用分页技术的早期版本中,S_ISVTX位被称为粘住位(sticky bit)。如果一个可执行程序文件的这一位被设置了,那么在该程序第一次被执行并结束时,其程序正文部分的一个副本仍被保存在交换区。(程序的正文部分是机器指令部分)。这使得下次执行该程序时能较快地将其装入内存中。其原因是:交换区占用连续磁盘空间,可将它视为连续文件,而且一个程序的正文部分在交换区中也是连续存放的,而在一般... 阅读全文
posted @ 2014-01-02 20:29 ITtecman 阅读(629) 评论(0) 推荐(0) 编辑
摘要:本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。这两个函数使我们可以更改现有文件的访问权限:#include int chmod( const char *pathname, mode_t mode );int fchmod( int filedes, mode_t mode );两个函数返回值:若成功则返回0,若出错则返回-1chmod函数在指定的文件上进行操作,而fchmod函数则对已打开的文件进行操作。为了改变一个文件的权限位,进程的有效用户ID必须等于文件的所有者ID,或者该进程必须具有超级用户 阅读全文
posted @ 2014-01-02 20:08 ITtecman 阅读(6107) 评论(0) 推荐(0) 编辑
摘要:本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。umask函数为进程设置文件模式创建屏蔽字,并返回以前的值。(这是少数几个没有出错返回函数中的一个。)#include mode_t umask( mode_t cmask);返回值:以前的文件模式创建屏蔽字其中,参数cmask是由S_IRUSR、S_IWUSR、S_IXUSR、S_IRGRP、S_IWGRP、S_IXG、S_IROTH、S_IWOTH及S_IXOTH这9个常量中的若干个按位“或”构成的。在进程创建一个新文件或新目录时,就一定会使用文件模式 阅读全文
posted @ 2014-01-02 18:14 ITtecman 阅读(1328) 评论(0) 推荐(0) 编辑
摘要:本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。当用open函数打开一个文件时,内核以进程的有效用户ID和有效组ID为基础执行其访问权限测试。有时,进程也希望按其实际用户ID和实际组ID来测试其访问能力。例如当一个进程使用设置用户ID或设置组ID特征作为另一个用户(或组)运行时,就可能会有这种需要。即使一个进程可能已经因设置用户ID以超级用户权限运行,它仍可能想验证其实际用户能否访问一个给定的文件。access函数是按照实际用户ID和实际组ID进行访问权限测试的。(该测试也分成四步,这与http://w 阅读全文
posted @ 2014-01-02 17:15 ITtecman 阅读(638) 评论(0) 推荐(0) 编辑
摘要:首先需要明确的是,新目录的所有权规则与新文件所有权规则相同。 新文件的用户ID设置为进程的有效用户ID。关于组ID,POSIX.1允许实现选择下列之一作为新文件的组ID。 (1)新文件的组ID可以是进程的有效组ID。 (2)新文件的组ID可以是它所在目录的组ID。 使用POSIX.1所允许的第二个选项(继承目录的组ID)使得在某个目录下创建的文件和目录都具有该目录的组ID。于是文件和目录的... 阅读全文
posted @ 2014-01-02 16:42 ITtecman 阅读(484) 评论(0) 推荐(0) 编辑
摘要:st_mode值也包含了针对文件的访问权限位。所有文件类型(目录文件、字符特殊文件等)都有访问权限(access permission)。每个文件有9个访问权限位,可将它们分成三类,见表4-5:表4-5 9个访问权限位,取自st_mode屏蔽意义S_IRUSR用户-读S_IWUSR用户-写S_IXUSR用户-执行S_IRGRP组-读S_IWGRP组-写S_IXGRP组-执行S_IROTH其他-读S_IWOTH其他-写S_IXOTH其他-执行在表4-5开头三行中,术语用户指的是文件所有者(owner)。chmod(1)命令用于修改这9个权限位。该命令允许我们用u表示用户(所有者),用g表示组,用 阅读全文
posted @ 2014-01-02 16:27 ITtecman 阅读(1737) 评论(0) 推荐(0) 编辑
摘要:与一个进程相关联的ID有6个或更多,它们如表4-4所示:表4-4 与每个进程相关联的用户ID和组ID实际用户ID 我们实际上是谁 实际组ID 有效用户ID 用于文件访问权限检查 有效组ID 附加组ID 保存的设置用户ID 由exec函数保存 保存的设置组ID 实际用户ID和实际组ID标识我们究竟是谁(执行这个程序的用户和组)。这两个字段在登录时取自口令文件中的登录项。通常,在一个登录会话间这些值并不改变,但是超级用户进程有方法改变它们。有效用户ID,有效组ID以及附加组ID决定了我们的文件访问权限。保存设置用户ID... 阅读全文
posted @ 2014-01-02 14:24 ITtecman 阅读(1500) 评论(0) 推荐(0) 编辑
摘要:本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。UNIX系统的大多数文件是普通文件或目录,但是也有另外一些文件类型。文件类型包括如下几种:(1)普通文件(regular file)。这是最常见的文件类型,这种文件包含了某种形式的数据。至于这种数据是文本还是二进制数据对于UNIX内核而言并无区别。对普通文件的解释由处理该文件的应用程序进行。一个值得注意的例外是二进制可执行文件。为了执行程序,内核必须理解其格式。所有二进制可执行文件都遵循一种格式,这种格式使内核能够确定程序文本和数据的加载位置。(2)目录文 阅读全文
posted @ 2014-01-02 11:15 ITtecman 阅读(2033) 评论(0) 推荐(0) 编辑
摘要:#include int stat( const char *restrict pathname, struct stat *restrict buf );int fstat( int filedes, struct stat *buf );int lstat( const char *restrict pathname, struct stat *restrict buf );三个函数的返... 阅读全文
posted @ 2014-01-02 10:00 ITtecman 阅读(2619) 评论(0) 推荐(0) 编辑
摘要:一些基本系统数据类型可以在多个头文件中定义。例如,在FreeBSD5.2.1中,size_t在26个不同的头文件中都有定义。由于一个程序可能包含这26个不同的头文件,并且ISO C不允许对同一个名字进行多次类型定义,那么我们该如何编写这些头文件呢?下面是FreeBSD中使用的技术: 首先,在头文件中定义可在多个头文件中出现的基本数据类型。例如: #ifndef _MACHINE__TYP... 阅读全文
posted @ 2014-01-02 09:06 ITtecman 阅读(731) 评论(0) 推荐(0) 编辑
摘要:转自:http://blog.csdn.net/lmh12506/article/details/6803847 首先要明白不带缓冲的概念:所谓不带缓冲,并不是指内核不提供缓冲,而是只单纯的系统调用,不是函数库的调用。系统内核对磁盘的读写都会提供一个块缓冲,当用write函数对其写数据时,直接调用系统调用,将数据写入到块缓冲进行排队,当块缓冲达到一定的量时,才会把数据写入磁盘。因此所谓的不带缓冲... 阅读全文
posted @ 2014-01-02 08:43 ITtecman 阅读(1188) 评论(1) 推荐(1) 编辑
摘要:较新的系统都提供名为/dev/fd的目录,其目录项是名为0、1、2等的文件。打开文件/dev/fd/n等效于复制描述符n(假定描述符n是打开的)。在下列函数调用中:fd = open( "/dev/fd/0", mode );大多数系统忽略它所指定的mode,而另外一些则要求mode必须是所涉及的文件(在这里则是标准输入)原先打开时所使用的mode的子集。因为上面的打开等效于:fd = dup( 0 );所以描述符0和fd共享同一文件表项。例如,若描述符0先前被打开为只读,那么我们也只能对fd进行读操作。即使系统忽略打开模式,并且下列调用成功:fd = open( &quo 阅读全文
posted @ 2014-01-01 09:04 ITtecman 阅读(2293) 评论(0) 推荐(0) 编辑
摘要:ioctl函数是I/O操作的杂物箱。不能用其他函数表示的I/O操作通常都能用ioctl表示。终端I/O是ioctl的最大使用方面。ioctl函数通过对文件描述符发送特定的命令来控制文件描述符所代表的设备。#include /* System V */#include /* BSD and Linux */#include /* XSI STREAMS */int ioctl( int filedes, int request, ... );返回值:若出错则返回-1,若成功则返回其他值对于ISO C原型,它用省略号表示其余参数。但是,通常只有另外一个参数,它常常是... 阅读全文
posted @ 2014-01-01 08:45 ITtecman 阅读(11411) 评论(0) 推荐(0) 编辑
摘要:fcntl函数可以改变已打开的文件的性质。#include int fcntl( int filedes, int cmd, ... /* int arg */ );返回值:若成功则依赖于cmd,若出错则返回-1在本节的各实例中,第三个参数总是一个整数,与上面所示函数原型中的注释部分相对应。但是在说明记录锁时,第三个参数则是指向一个结构的指针。fcntl函数有5种功能:(1)复制一个现有的描述符(cmd = F_DUPFD )。(2)获得/设置文件描述符标记(cmd = F_GETFD或F_SETFD)。(3)获得/设置文件状态标志(cmd = F_GETFL或F_SETFL)。(4)获得/设 阅读全文
posted @ 2014-01-01 08:24 ITtecman 阅读(1191) 评论(0) 推荐(0) 编辑

点击右上角即可分享
微信分享提示