`
mylxiaoyi
  • 浏览: 327582 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论
文章列表
搜索数据库 在CD关键字上的搜索比较复杂。函数的用户希望一旦调用就启动一个搜索。我们在第7章通过将在第一次调用上的*first_call_ptr设置为true并且函数返回第一个匹配结果来满足这种需求。在接下来的搜索函数调用中,*first_call_ptr设置为false,从而会返回更多的匹配,每次调用返回一个匹配结果。 现在我们已经将程序分为两个进程,我们不能再允许搜索在服务器端一次处理一个实体,因为另一个不同的客户端也许会由服务器请求一个不同的搜索,而我们的搜索仍在处理之中。我们不能使得服务器端为每一个客户端单独存储搜索内容(搜索已经进行到哪里),因为当一个用户找到他们要找的CD关键 ...
CD数据库程序 现在我们已经了解了我们可以如何使用有名管道来实现一个简单的客户端/服务器系统,我们可以重新查看我们的CD数据库程序并且进行相应的修改。我们同时组合了一些信号处理从而允许我们在进程被中断时进行一些清理动作。我们会使用我们前面的具有一个命令行接口的dbm版本,从而进可能直接的查看代码。 在我们更为详细的讨论新版本的代码之前,让我们先编译这个程序。如果我们有由Web站点所获得的源代码,就可以使用makefile来编译生成server与client程序。 输入server -i使得程序初始化一个新的CD数据库。 无需多言,客户端直到服务器启动并运行时才运行。下面是makefi ...
读取与写入FIFO 使用O_NONBLOCK模式会影响作用在FIFO上的read与write调用的行为。 在一个空的阻塞FIFO(例如,没有使用O_NONBLOCK打开的)上的read调用将会等待直到有数据可以读取。相反,在非阻塞且没有数据的FIFO上进行read调用将会返回0字节。 在一个完全阻塞的FIFO上的write调用将会等待直到数据可以写入。在一个不能全部接受所有将要写入数据的FIFO上的write调用将会: 如果请求PIPE_BUF字节或是小于且数据不能写入时将会失败。 如果请求大于PIPE_BUF字节将会写入部分数据,返回实际写入的字节数据,其值为0。 FIFO的大 ...
有名管道:FIFO 到目前为止,我们只是可以在两个相关的程序之间传递数据,也就是说,由一个共同的祖先进程启动的程序。通常这并不是十分方便,因为我们希望不相关的进程也可以交换数据。 我们可以使用FIFO来实现这个操作,通常称之为有名管道。一个有名管道是在文件系统中作为名字存在的一个特殊的文件类型(记住,在Linux一切皆文件),但是行为类似于我们已经了解的无名管道。 我们可以通过命令行或是在一个程序内部创建有名管道。由于历史原因,用于创建有名管道的命令为mknod: $ mknod filename p 然而,mknod命令并不在X/Open命令列表中,所以他并不是在所有的类Unix ...
父子进程 我们的pipe调用探索的下一步就是使得子进程是与父进程不同的一个程序,而不是运行相同程序的另一个进程。我们可以使用exec调用来完成这个任务。这样做的一个困难就是通过exec执行的新进程需要知道访问哪一个文件描述符。在exec调用之后,就不再是这样的情况了,因为老进程已经被新的子进程所替代。我们可以通过向exec所执行的新进程传递文件描述符作为参数就可以解决这个问题。 要显示这是如何工作的,我们需要两个程序。第一个就是数据生产者,他创建管道并且调用子进程,数据消费者。试验--管道与exec 1 作为第一个程序,我们将pipe2.c修改为pipe3.c。对比这两个文件我们可 ...
管道调用 我们已经了解了高层的popen函数,现在我们继续来了解低层的pipe函数。这个函数提供了一个在两个函数之间传递数据的方法,而不必调用shell来解释所请求的命令的。同时他也为我们提供了更多的数据读写控制。 pipe函数的原型如下: #include <unistd.h> int pipe(int file_descriptor[2]); pipe函数接受一个两个整数文件描述符的数组作为参数。他会使用两个新的文件描述符来填充这个数据并且返回一个零值。如果失败则会返回-1并且设置errno来指明失败原因。Linux手册页中所定义的错误如下: EMFILE:进程正 ...
传递更多的数据 到目前为止我们所用的机制只是简单的在一个fread或是fwrite中发送或是接收全部的数据。有时我们也许以更小的尺寸发送数据,或是也许我们并不知道输出的大小。为了避免声明一个大的缓冲区,我们可以使用 ...
第13章 进程间通信:管道 在第11章,我们了解了使用信号在两个进程之间发送消息的一个简单方法。我们创建了可以用来引起响应的通知事件,但是所传递的信息限制于一个信号数量。 在这一章,我们将会了解管道,这会允许在进程之间交换更为有用的数据。在本章的结尾,我们将会使用我们的新知识来重新将CD数据库程序实现为一个非常简单的客户/服务器程序。 在本章,我们将会涉及下列主题: 管道的定义 处理管道 管道调用 父子进程 有名管道:FIFO 客户端/服务器方法什么是管道? 当我们由一个进程到另一个进程连接数据流时我们使用术语管道。通常我们将一个进程的输出连接到另一个进程的输入。 ...
线程属性-调度 下面我们来看一下我们也许希望改变的第二个线程属性:调度。改变调度属性与设置分离属性相类似,但是我们可以使用另外两个函数来查找可用的等级级别,sched_get_priority_max与sched_get_priority_min。 试验--调度 因为thread6.c是与前面的例子十分类似,这里我们只看一下其中的区别。 1 首先,我们需要一些额外的变量: int max_priority; int min_priority; struct sched_param scheduling_value; 2 在我们设置分离属性之后,我们设置调度策略。 res ...
线程属性 当我们第一次了解线程时,我们并没有讨论线程属性的问题。我们现在会进行讨论。线程有许多我们可以控制的属性。然而,在这里我们只讨论那些我们最需要的线程属性。其他属性的详细信息可以在手册中了解到。 在所有我们前面的例子中,我们不得不在允许程序退出之前使用pthread_join来重新同步我们的线程。如里我们希望允许一个线程向创建他的线程返回数据时我们需要这样做。有时我们并不需要第二个线程向主线程返回信息,也不希望主线程等待第二个线程。 假设我们创建了第二个线程来备份正在编辑的数据文件的一份拷贝,而主线程继续向用户服务。当备份完成时,第二个线程只是简单的退出,并没有需要与主线程聚合。 ...
使用互斥同步 在多线程程序中同步访问的另一个方法就是使用互斥,其作用允许程序锁住一个对象,从而只有一个线程可以访问他。要控制对临界区代码的访问,在我们进入这段代码之前锁住一个互斥量,并且在我们完成操作时进行解锁。 使用互斥所需要基本函数与信号量所需要的函数相似,其声明如下: #include <pthread.h> int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr); int pthread_mutex_lock(pthread_mutex_t *mu ...
并发执行 下面我们将要编写一个检测两个线程是否并发执行的程序。因为我们还没有了解要有效完成这一任务所需要的线程同步的知识,所以这并不是一个高效完成在线程之间称之为池操作的程序。再一起说明,我们要利用这一事实,在一个进程内部的不同线程之间共享除了局部函数变量之外的所有变量。 试验--两个线程的同步执行 在这一部分,我们所创建的程序thread2.c,是对thread1.c进行了简单的修改而得来的。我们添加一个额外的文件域变量来测试哪一个线程正在运行: int run_now = 1; 当主函数执行时我们将其设置为1,而当我们的新线程执行时我们将其设置为2。 在main函数时,在新线 ...
第一个线程程序 有一个完整的与线程相关的库调用集合,其中的大多数名字以pthread_开头。要使用这些库调用,我们必须定义宏_REENTRANT,包含文件pthread.h,并且使用-lpthread来链接线程库。 当设计原始的Unix与POSIX库函数时,假 ...
第12章 POSIX线程 在第11章,我们看到在Linux中进程是如何被处理的。这些多进程的特性很久以来就是类Unix操作系统的特性。有时使用fork创建一个新进程的代价实在是太大了。在这种情况下,使得一个程序同时做两件事情,或者 ...
健壮的信号接口 我们已经讨论了使用signal来发出与捕获信号,因为他们在较为旧的Unix程序中很常见。然而,X/Open与Unix规范推荐了一个更为健壮的用于信号处理的新的编程接口:sigaction。 #include <signal.h> int sigaction(int sig, const struct sigaction *act, struct sigaction *oact); sigaction结构定义在signal.h中,这个结构用于定义依据由sig所指定的信号而所要采取的动作,而且这个结构至少有以下几个成员: void (*) (int) sa_ ...
Global site tag (gtag.js) - Google Analytics