- 博客(136)
- 资源 (2)
- 收藏
- 关注
原创 9.10 内核同步方法_顺序和屏障
rmb()方法提供了一个“读”内存屏障,它确保跨越rmb()的载入动作不会发生重排序。也就是说,在rmb()之前的载入操作不会被重新排在该调用之后,同理,在rmb()之后的载入操作不会被重新排在该调用之前。 wmb()方法提供了一个“写”内存屏障,这个函数的功能和rmb()类似,区别仅仅是它是针对存储而非载入--它确保跨越屏障的存储不发生重排序。 mb()方法既提供了读屏障也提供了些屏障。
2010-10-19 00:35:00
687
原创 9.9 内核同步方法_禁止抢占
内核抢占代码使用自旋锁作为非抢占区域的标记。如果一个自旋锁被持有,内核便不能进行抢占。 可以通过preempt_disable()禁止内核抢占。这是一个可以嵌套调用的函数,可以调用任意次。每次调用都必须有一个相应的preempt_enable()调用。当最后一次preempt_enable()被调用,内核抢占才重新启用。
2010-10-19 00:30:00
701
原创 9.7 内核同步方法_完成变量
<br /> 如果在内核中一个任务需要发出信号通知另一个任务发生了某个特定事件,利用完成变量是使两个任务得以同步的简单方法。
2010-10-19 00:26:00
506
原创 9.5 内核同步方法_读-写信号量
<br /> 所有的读-写信号量都是互斥信号量(也就是说,它们的引用计数等于1)。所有读-写锁的睡眠都不会被信号打断,所以它只有一个版本的down()操作。<br /> 读-写信号量相比读-写自旋锁多一种特有的操作:downgrade_writer()。这个函数可以动态地将获取的写锁转换为读锁。
2010-10-19 00:23:00
486
原创 9.4 内核同步方法_信号量
<br /> Linux的信号量是一种睡眠锁。如果有一个任务试图获得一个已经被占用的信号量时,信号量会将其推进一个等待队列;,然后让其睡眠。当持有信号量的进程将信号量释放后,处于等待队列中的那个任务将被唤醒,并获得该信号量。由于执行线程在锁被争用时会睡眠,所以只能在进程上下文中才能获取信号量锁,因为在中断上下文是不能进行调度的。在占用信号量的同时不能占用自旋锁。因为在等待信号量时可能会睡眠,而在持有自旋锁时是不允许睡眠的。<br /> 信号量不同于自旋锁,他不会禁止内核抢占,所以持有信号量的代码
2010-10-19 00:15:00
458
原创 9.3 内核同步方法_读-写自旋锁
<br /> 一个或多个读任务可以并发的持有读者锁;相反,用于写的锁最多只能被一个写任务持有,而且此时不能有并发的读操作。有时把读/写锁叫做共享/排斥锁,或者并发/排斥锁,因为这种锁以共享(对读者而言)和排斥(对写者而言)的形式获得使用。<br /> 注意不能把一个读锁“升级”为写锁。这种代码:read_lock(&mr_rwlock);write_lock(&mr_rwlock);<br /> 将会带来死锁,因为写锁会不断自旋,等待所有的读者释放锁,其中也包括它自己。所以当确实需要写操作
2010-10-19 00:06:00
427
原创 9.2 内核同步方法_自旋锁
<br /> Linux内核中最常见的锁是自旋锁。自旋锁最多只能被一个可执行线程持有。<br /> 自旋锁不应该被长时间持有。持有自旋锁的时间最好小于完成两次上下文切换的耗时。<br /> 警告:自旋锁是不可递归的!<br /> 自旋锁可以使用在中断处理程序中(此外不能使用信号量,因为它们会导致睡眠)。在中断处理程序中使用自旋锁时,一定要在获取锁之前,首先禁止本地中断(当前处理器上的中断请求),否则,中断处理程序就会打断正持有锁的内核代码,有可能试图去争用这个已经被持有的自旋锁。注意,需要
2010-10-18 23:57:00
398
原创 9.1 内核同步方法_原子操作
<br /> 内核提供了两组原子操作接口--一组对整数进行操作,另一组对单独的位进行操作。<br /> 9.1.1 原子整数操作<br /> 针对整数的原子操作只能对atomic_t类型的数进行处理。在这里之所以引入了一个特殊数据类型,而没有直接使用C语言的int类型,主要是出于两个原因:首先,让原子函数只接受atomic_t类型的操作数,可以确保原子操作只与这种特殊类型数据一起使用。其次,使用atomic_t类型确保编译器不对相应的值进行访问优化--这点使得原子操作最终接收到正确的内存地址,而
2010-10-18 23:37:00
429
原创 8 内核同步介绍
8.1 临界区和竞争条件<br /> 所谓临界区就是访问和操作共享数据的代码段。如果两个执行线程有可能处于同一个临界区中,就称它是竞争条件。避免并发和防止竞争条件被称为同步。<br /> 8.2 加锁<br /> 各种锁机制之间的区别主要在于当锁被争用时(已经被使用)的行为表现--一些锁会简单地执行忙等待,而有些锁会使当前任务睡眠直到锁可用为止。<br /> 8.2.1 到底是什么造成了并发执行<br /> 用户空间之所以需要同步,是因为用户程序会被调度程序抢占和重新调度。<br />
2010-10-09 00:39:00
473
原创 3.4 表、栈和队列_队列ADT
<br /> 像栈一样,队列也是表。使用队列时插入在一端进行而删除则在另一端进行。<br /> 3.4.1 队列模型<br /> 队列的基本操作时Enqueue(入队),它是在表的末端(叫做队尾(rear))插入一个元素,还有Dequeue(出队),它是删除(或返回)在表的开头(叫做队头(front))的元素。<br /> 3.4.2 队列的数组实现<br />
2010-09-03 00:00:00
642
原创 3.2 表、栈和队列_栈ADT
3.3.1 栈模型 栈是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈的顶。对栈的基本操作有Push(进栈)和Pop(出栈),前者相当于插入,后者则是删除最后插入的元素。对空栈进行的Pop或Top一般被认为是栈ADT的错误。另一方面,当运行Push时空间用尽是个实现错误,但不是ADT错误。 栈有时又叫做LIFO(后进先出)表。 一般的模型是,存在某个元素位于栈顶,而该元素是唯一的可见元素。3.3.2 栈的实现 由于栈是一个表,因此任何实现表的方法都能实现栈。栈的链表
2010-09-01 23:54:00
968
原创 3.2 表、栈和队列_表ADT
大小为0的表为空表。对于除空表外的任何表,Ai+1后继Ai(或继Ai之后)并称Ai-1(i1)。表中的第一个元素是A1,而最后一个元素是AN。不定义A1的前驱元,也不定义AN的后继元。3.2.2 链表 为了避免插入和删除的线性开销,需要允许表可以不连续存储,否则表的部分或全部需要整体移动。 链表有一系列不必在内存中相连的结构组成。每一个结构均含有表元素和指向包含该元素的后继元的结构的指针。3.2.3 程序设计细节
2010-08-31 00:54:00
551
转载 c与c++混合编程(下)
<br />Mixing C and C++ Code in the Same Program<br /> <br />By Stephen Clamage, Sun Microsystems, Sun ONE Studio Solaris Tools Development Engineering<br /> <br />Translator: Qiu Longbin <robin.qiu(at)yeah.net><br /> <br />C++语言提供了一个混合代码的机制,使得代码可以在同一个程序中被兼
2010-08-30 17:00:00
1249
转载 c与c++混合编程(上)
[32] How to mix C and C++ 如何混合使用C和C++<br />(Part of C++ FAQ Lite, Copyright © 1991-2006, Marshall Cline, cline@parashift.com)Translator: Qiu Longbin <robin.qiu(at)yeah.net> FAQs in section [32]:· [32.1] 混合使用C和C++代码时我需要知道什么?· [32.2] 如何在C++代码里inc
2010-08-30 16:57:00
654
转载 c与c++混合编程(CU)
1.引言 C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同。作为一种欲与C兼容的语言,C++保留了一部分过程式语言的特点(被世人称为“不彻底地面向对象”),因而它可以定义不属于任何类的全局变量和函数。但是,C++毕竟是一种面向对象的程序设计语言,为了支持函数的重载,C++对全局函数的处理方式与C有明显的不同。2.从标准头文件说起 某企业曾经给出如下的一道面试题: 面试题 为什么标准头文件都有类似
2010-08-30 16:48:00
1106
原创 7.4 下半部和推后执行的工作_工作队列
<br /> 工作队列可以把工作推后,交由一个内核线程去执行--这个下半部分总是会在进程上下文执行。这样,通过工作队列执行的代码能占尽进程上下文的所有优势。最重要的就是工作队列允许重新调度甚至是睡眠。<br /> 通常,在工作队列和软中断/tasklet中作出选择非常容易。如果推后执行的任务需要睡眠,那么就选择工作队列。如果推后执行的任务不需要睡眠,那么就选择软中断或tasklet。<br /> 如果你需要用一个可以重新调度的实体执行你的下半部处理,你应该使用工作队列。它是唯一能在进程上下
2010-08-27 00:20:00
1181
原创 7.2 下半部和推后执行的工作_tasklet
7.3.1 tasklet的实现<br /> 因为tasklet是通过软中断实现的,所以它们本身也是软中断。tasklet由两类软中断代表:HI_SOFTIRQ和TASKLET_SOFTIRQ。这两者之间唯一的实际区别在于HI_SOFTIRQ类型的软中断先于TASKLET_SOFTIRQ类型的软中断执行。<br /> 1. tasklet结构体<br /> tasklet有tasklet_struct结构表示。每个结构体单独代表一个tasklet,它在<linux/interrupt.h>中定义
2010-08-26 00:34:00
691
原创 7.2 下半部和推后执行的工作_软中断
7.2.1 软中断的实现 软中断是在编译期间静态分配的。它不像tasklet那样能被动态地注册或去除。软中断由softirq_action结构表示,它定义在:struct softirq_action{ void (*action) (struct softirq_action *); void *data;} 1. 软中断处理程序 一个软中断不会抢占另外一个软中断。实际上,唯一可以抢占软中断的是中断处理程序。不过,其他的软中断--甚至是相同类型的软中断--可以在其他处理器上同时执行
2010-08-25 22:33:00
796
1
原创 7.1 下半部和推后执行的工作_下半部
<br /> 下半部的任务就是执行与中断处理密切相关但中断处理程序本身不执行的工作。记住,中断处理程序会异步执行,并且在最好的情况下它也会锁定当前的中断线。对于在上半部和下半部直接按划分工作,尽管不存在某种严格的规则,但还是有一些提示可供借鉴:如果一个任务对时间非常敏感,将其放在中断处理程序中执行。如果一个任务和硬件相关,将其放在中断处理程序中执行。如果一个任务要保证不被其他中断(特别是相同的中断)打断,将其放在中断处理程序中执行。其他所有任务,考虑放置在下半部执行。<br /> 7.1.1 为什么要
2010-08-25 00:51:00
538
原创 Eclipse
Eclipse 是IBM主持开发的优秀的开源IDE,可用于各种编程语言,例如Java,C、C++等。 1. 下载可以到 Eclipse 的官方网站下载,也可以下面这个地址直接下载Eclipse IDE for C/C++ Developers : Eclipse 3.6/Helios: http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/helios/R/eclipse-c
2010-08-14 16:38:00
1333
原创 5.13 标准I/O库_临时文件
ISO C标准I/O库提供了两个函数以帮助创建临时文件。#include char *tmpnam(char *ptr);返回值:指向唯一路径名的指针FILE *tmpfile(void);返回值:成功返回文件指针,出错返回NULLtmpnam函数产生一个与现有文件名不同的一个有效路径名字符串。每次调用它时,它都产生一个不同的路径名,最多调用次数是TMP_MAX。TMP_MAX定义在中。 若ptr是NULL,则所产生的路径名存放在一个静态区中,指向该静态区的指针作为函数值返回。下一次在调用tm
2010-08-13 17:08:00
558
原创 5.12 标准I/O库_实现细节
<br /> 在UNIX系统中,标准I/O库最终都要调用第3章中说明的I/O例程。每个标准I/O流都有一个与其相关联的文件描述符,可以对一个流调用fileno函数以获得其描述符。#include <stdio.h>int fileno(FILE *fp);<br />返回值:与该流相关联的文件描述符
2010-08-12 11:01:00
366
原创 5.11 标准I/O库_格式化I/O
1. 格式化输出<br /> 执行格式化输出处理的是4个printf函数。#include <stdio.h>int printf(const char *restrict format, ...);int fprintf(FILE *restrict fp, const char *restrict format, ...);<br />返回值:成功返回输出字符数,出错返回负值int sprintf(char *restrict buf, const char *restrict format, .
2010-08-12 10:46:00
591
原创 5.10 标准I/O库_定位流
有三种方法定位标准I/O流。ftell和fseek函数。它们都假定文件的位置可以存放在一个长整型中。ftello和fseeko函数。可以使文件偏移量不必一定使用长整型。它们使用off_t数据类型代替了长整型。fgetpos和fsetpos函数。这两个函数是由ISO C引入的。它们使用一个抽象数据类型fpos_t记录文件的位置。这种数据类型可以定义为记录一个位置所需的长度。#include long ftell(FILE *fp);返回值:成功返回当前文件位置指示,出错返回-1Lint fseek(F
2010-08-10 17:58:00
781
原创 5.9 标准I/O库_二进制I/O
<br /> 下列两个函数执行二进制I/O操作:#include <stdio.h>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);<br />返回值:读或写的对象数<br /> 这两个函数有两种常见的用法:读或写一个二进
2010-08-10 16:17:00
439
原创 5.7 标准I/O库_每次一行I/O
<br /> 下面两个函数提供每次输入一行的功能。#include <stdio.h>char *fgets(char *restrict buf, int n, FILE *restrict fp);char *gets(char *buf);<br />返回值:成功返回buf,已到达文件结尾或出错则返回NULL<br />这两个函数都指定了缓冲区的地址,读入的行将送入其中。gets从标准输入读,而fgets则从指定的流读。<br /> 对于fgets,必须指定缓冲区的长度n。此函数一直读到下
2010-08-09 15:48:00
417
原创 5.6 标准I/O库_读和写流
一旦打开了流,则可在三种不同类型的非格式化I/O中进行选择,对其进行读、写操作:每次一个字符的I/O。一次读或写一个字符,如果流是带缓冲的,则标准I/O函数会处理所有缓冲。每次一行的I/O.直接I/O。直接I/O这个术语来自ISO C标准,有时也被称为二进制I/O、一次一个对象I/O、面向记录的I/O表面向结构的I/O。 1. 输入函数 以下三个函数可用于一次读一个字符:#include int getc(FILE *fp);int fgetc(FILE *fp);int getchar(vo
2010-08-09 11:54:00
505
原创 5.5 标准I/O库_打开流
下列三个函数打开一个标准I/O流。#include FILE *fopen(const char *restrict pathname, const char *restrict type);FILE *fropen(const char *restrict pathname, const char *restrict type, FILE *restrict fp);FILE *fdopen(int filedes, const char *type);返回值:成功返回文件指针,出错返回NULL
2010-08-07 17:10:00
813
原创 5.4 标准I/O库_缓冲
标准I/O提供了三种类型的缓冲。全缓冲: 在填满标准I/O缓冲区后才进行实际I/O操作。对于驻留在磁盘上的文件通常是有标准I/O库实施全缓冲。行缓冲: 当在输入和输出中遇到换行符时,标准I/O库执行I/O操作。当涉及一个终端(例如标准输入和输出),通常使用行缓冲。对于行缓冲有两个限制。第一,因为标准I/O库用来收集每一行的缓冲区的长度是固定的,所以只要填满了缓冲区,那么即使还没有写一个换行符,也进行I/O操作。第二,任何时候只要通过标准I/O库要求从(a)一个不带缓冲的流,或者(b)一个行缓冲的流(
2010-08-07 11:54:00
456
原创 5.3 标准I/O库_标准输入、标准输出和标准出错
<br /> 标准输入、标准输出和标准出错用文件描述符引用是:STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO,而用文件指针引用是:stdin、stdout和stderr。
2010-08-06 17:38:00
362
原创 5.2 标准I/O库_流和FILE对象
<br /> 在第3章中,所有I/O函数都是针对文件描述符的。而对于标准I/O库,它们的操作则是围绕流进行的。当用标准I/O库打开或创建一个文件时,我们已使一个流与一个文件相关联。<br /><br /> 对于ASCII字符集,一个字符用一个字节表示。对于国际字符集,一个字符可用多个字节表示。标准I/O文件流可用于单字节或多字节(“宽”)字符集。流的定向决定了所读、写的字符是单字节还是多字节的。当一个流最初被创建时,它并没有定向。如若在未定向的流上使用一个多字节I/O函数,则将该流的定向设置
2010-08-06 17:33:00
679
原创 3.18 文件I/O_习题
3.1<br /> 所有的磁盘I/O都要经过内核的块缓冲区(也称为内核的缓冲区高速缓存),唯一例外的是对原始磁盘设备的I/O。“不带缓冲的I/O”指的是在用户的进程中对这两个函数不会自动缓冲,每次read或write就要进程一次系统调用。<br /> 3.3<br /> 每次调用open函数就分配一个新的文件表项,调用dup引用已存在的文件表项。
2010-08-06 15:51:00
418
原创 3.17 文件I/O_小结
因为read和write都在内核执行,所以称这些函数为不带缓冲的I/O函数。 将ioctl用于STREAMS I/O系统,将fcntl用于记录锁。
2010-08-06 15:45:00
387
原创 3.16 文件I/O_/dev/fd
<br /> 打开文件/dev/fd/n等效于复制描述符n(假定描述符n是打开的)[dup]。<br /> 大多数系统忽略它所指定的mode,而另外一些则要求mode必须是所涉及的文件原先打开时所使用mode的子集。<br />
2010-08-06 15:41:00
623
原创 3.14 文件I/O_fcntl函数
<br /> fcntl函数可以改变已打开的文件的性质。#include <fcntl.h>int fcntl(it filedes, int cmd, .../* int arg */);<br />返回值:成功则依赖于cmd,出错返回-1<br /> fcntl函数有5中功能:复制一个现有的描述符(cmd=F_DUPFD)。获得/设置文件描述符标记(cmd=FD_GETFD或F_SETFD)。获得/设置文件状态标志(cmd=FD_GETFL或F_SETFL)。获得/设置异步I/O所有权(cm
2010-08-06 15:37:00
499
原创 6.7 中断和中断处理程序_中断控制
<br /> 一般来说,控制中断系统的原因归根到底是需要提供同步。<br /> 6.7.1 禁止和激活中断<br /> 用于禁止当前处理器(仅仅是当前处理器)上的本地中断,随后又激活它们的语句为:local_irq_disable();load_irq_enable();<br /> 如果在调用local_irq_disable()例程之前已经禁止了中断,那么该例程往往会带来潜在的危险;同样相应的load_irq_enable()例程也存在潜在危险,因为它将无条件地激活中断,尽管这些中断可
2010-08-05 00:45:00
707
原创 3.13 文件I/O_sync、fsync和fdatasync函数
<br /> 当将数据写入文件时,内核通常先将该数据复制到其中一个缓冲区中,如果该缓冲去尚未写满,则并不将其排入输出队列,而是等待其写满或者当内核需要重用该缓冲区以便存放其他磁盘块数据时,再将该缓冲排入输出队列,然后待其到达队首时,才进行实际的I/O操作。这种输出方式被成为延迟写。<br /> 为了保证磁盘上实际文件系统与缓冲区高速缓存中内容的一致性,UNIX系统提供了sync、fsync和fdatasync三个函数。#include <unistd.h>int fsync(int filede
2010-08-04 18:04:00
1316
原创 3.12 文件I/O_dup和dup2函数
下面两个函数都可用来复制一个现存的文件描述符:#include int dup(int filedes);int dup2(int filedes, int filedes2);返回值:成功返回新的文件描述符,出错返回-1 有dup返回的新文件描述符一定是当前可用文件描述符的最小数值。用dup2则可以用filedes2参数指定新描述符的数值。如果filedes2已经打开,则先将其关闭。如若filedes等于filedes2,则dup2返回filedes2,而不关闭它。 这些函数返回的新文
2010-08-04 17:46:00
565
原创 3.11 文件I/O_原子操作
1. 添写至一个文件 任何一个需要多个函数调用的操作都不可能是原子操作,因为在两个函数调用之间,内核有可能会临时挂起该进程。 UNIX系统提供了一种方法使这种操作成为原子操作,该方法是在打开文件时设置O_APPEND标志。这就使内核每次对这种文件进行写之前,都将进程的当前偏移量设置到该文件的尾端处,于是在每次写之前就不再需要调用lseek。 2. pread和pwrite函数 Single UNIX Specification包括了XSI扩展,该扩展允许原子性地定位搜索(seek)和执行I
2010-08-04 16:12:00
898
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人