Linux库的概念 库是一种软件组件技术,库里面封装了数据和函数,提供给用户程序调用。库的使用可以使程序模块化,提高程序的编译速度,实现代码重用,使程序易于升级。 Windows本身提供并使用了大量的库,包括静态链接库(.lib文件)和动态链接库(.dll文件)。类似的,Linux操作系统也使用库。Linux系统中,通常把库文件存放在/usr/lib或/lib目录下。Linux库文件名由前缀lib,库名以及后缀3部分组成,其中动态库以.so作为后缀,静态库通常以.a作为后缀。 Linux库的载入顺序 在使用静态库和动态库的时候,它们的载入顺序是不一样的。静态库的代码在编译时就拷贝到应用程序中,因此当多个应用程序同时引用一个静态库函数时,内存中将会有调用函数的多个副本。这样的优点是节省编译时间。而动态库是在程序开始运行后调用库函数时才被载入,被调函数在内存中只有一个副本,并且动态库是可以在程序运行期间释放动态库所占用的内存,腾出空间供其他程序使用。 什么是库 库是写好的现有的,成熟的,可以复用的代码。现实中每 继续阅读 >>


董恒毅 16/10/12 19:19:55
概述 共享内存就是分配一块能被其他进程访问的内存。 共享内存的数据结构 共享内存和消息队列,信号量一样,在内核中也维护着一个内部结构。 #include<linux/shm.h> { struct ipc_perm shm_perm; int shm_segsz; __kernel_time_t shm_atime; __kernel_time_t shm_dtime; __kernel_time_t shm_ctime; __kernel_ipc_pid_t shm_cpid; __kernel_ipc_pid_t shm_lpid; unsigned short shm_nattch; unsigned short shm_unused; void *shm_unused2; vo 继续阅读 >>


董恒毅 16/10/12 12:21:12
概述 信号量是一个计数器,常用于解决线程和进程的同步问题,特别是对临界资源的同步。 临界资源就是某一时刻只能由一个进程或线程进行操作的资源,这里的资源可以是一段代码,一个变量或某种硬件资源。信号量的值大于或等于0表示可供并发进程使用的资源实体数,小于0表示等待使用临界资源的进程数。 信号集的数据结构 #include<linux/sem.h> struct semid_ds { struct ipc_perm sem_perm; //操作权限 _kernel_time_t sem_otime; //对信号进行操作的最后时间 _kernel_time_t sem_ctime; //对信号进行修改的最后时间 struct sem *sembase; //指向第一个信号 struct sem_queue sem_pending; //等待处理的挂起操作 struct sem_queue **sem_pending_las 继续阅读 >>


董恒毅 16/10/10 20:15:30
概述 信号是一种软件中断,它提供了一种处理异步事件的方法,也是进程间惟一的异步通信方式。目前Linux信号不仅能告诉某一进程发生了什么事,还能给进程传递数据。 信号的来源 硬件方式 当用户在终端上按下某些键的时候,将产生信号,如CTRL+C组合键将产生SIGINT信号 硬件异常产生信号,如除数为0,无效的存储访问 软件方式 在终端下使用kill命令向进程发送任意信号 进程调用kill或sigqueue函数发送信号 当检测到某种软件条件已经具备时发出信号,由alarm或settimer设置的定时器超时将产生SIGALRM信号 信号的种类 在shell下输入kill-l可显示Linux系统支持的全部信号,如图: 信号的值在signal.h中定义,以上所有信号都有一定的含义,在此不一一陈述。 可靠信号与不可靠信号 在上图中,1号到31号之间的信号都是继承自UNIX系统,是不可靠的信号,33号到64号之间的信号都是可靠信号,也称为实时信号。 信号的可靠 继续阅读 >>


董恒毅 16/10/08 18:16:19
概述 进程间的通信,除过管道和命名管道之外,还有一种我认为是比上述两种方式更优秀的通信方式,那就是消息队列。 消息队列的基本概念 消息队列是一个存放在内核中的消息链表,每个消息队列是由消息读列标识符标识。它与之前两种进程间通信方式不同的就是,它是存在于内核之中的,只有在内核重启的时候或是显式的删除一个消息队列的时候,该消息队列才会真正的删除。 要操作消息队列,需要用到一些数据结构,熟悉并掌握这些数据结构对消息队列的理解是很重要的。 消息缓冲结构 向消息队列发送消息时,必须组成合理的数据结构。Linux定义了一个模板数据结构msgbuf。 #include<linux/msg.h> struct msgbuf { long mtype; char mtext[1]; }; //mtype表示的是消息类型,给消息指定类型,可以使消息在一个队列之中重复的使用。mtext指消息的内容。 注意: mtext虽然定义为char类型,但并不代表消息内容只能是一个字符,它是任意类型,它可以由用户定义。 继续阅读 >>


董恒毅 16/10/08 00:39:36
概述 对于进程间通信,由于管道的种种约束与不便,我们聪明的人类必然会想办法对其进行完善,以便使程序更加完美,然后就有了有名管道的诞生。 有名管道 有名管道也被称为FIFO,它的提出克制了管道在使用上面的不足,管道只能在有亲缘关系的进程间使用,而有名管道可以使不同的两个进程进行通信。 有名管道的实现原理 有名管道提供了一个路径名使之与自己关联,并且以FIFO的文件形式存储在文件系统中。有名管道就是一个设备文件,因此就算进程之间不存在 亲缘关系,只要访问该路径,就可以相互通信。由于FIFO是按照先进先出的原则工作,所以第一个被写入有名管道的数据总是第一个被读出。 有名管道的创建和读写 shell下创建有名管道 shell命令:mknod, mkfifo mknod用法:mknod Name { b | c } Major Minor b表示块文件,c表示字符文件。 后面第一个参数指定主设备数目,第二个参数指定次设备数目。 系统函数创建有名管道 #include&l 继续阅读 >>


董恒毅 16/10/07 22:59:54
概述 网络编程里面的套接虽然强大,但是使用起来比较麻烦,并且如果只是单机之中不同的进程间通信,那么我们就不需要用网络套接字进行编程,我们有更好的办法! 管道 管道是一种半双工的通信方式,所谓半双工,就是数据只能单方向的进行流动,好比设置管道一的一端为A口,另一端为B口,则数据只能由A流向B。除此之外,管道还只能在有亲缘关系的进程间使用,通常指父子进程。 管道的局限性 管道的局限性是比较多的,除了上述两个缺点之外,它还没有名字,它的缓冲区大小是受限制的,它传递的是无格式的字节流,因为这个缺陷,它得要求输入方和输出方事先约好数据的格式。基于种种不便,除了一些简单的进程间通信,我们基本是不使用管道的。 管道的实现原理 当用管道进行两个进程间的通信的时候,其实使用的是系统设置的文件描述符,也就是说,管道其实就是一个特殊的文件,但是这个文件只存在于内存之中,在创建管道的时候,系统为管道分配一个页面作为数据缓冲区,进行通信的两个进程就是通过读写这个缓冲区实现的。 管道的创建和读写 #include< 继续阅读 >>


董恒毅 16/09/29 22:34:32
一。互斥量和条件变量简介 互斥量(mutex)从本质上说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁。对互斥量进行加锁以后,任何其他试图再次对互斥锁加锁的线程将会阻塞直到当前线程释放该互斥锁。如果释放互斥锁时有多个线程阻塞,所有在该互斥锁上的阻塞线程都会变成可运行状态,第一个变为运行状态的线程可以对互斥锁加锁,其他线程将会看到互斥锁依然被锁住,只能回去再次等待它重新变为可用。 条件变量(cond)是在多线程程序中用来实现”等待–》唤醒”逻辑常用的方法。条件变量利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待”条件变量的条件成立”而挂起;另一个线程使“条件成立”。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。线程在改变条件状态前必须首先锁住互斥量,函数pthread_cond_wait把自己放到等待条件的线程列表上,然后对互斥锁解锁(这两个操作是原子操作)。在函数返回时,互斥量再次被锁住。 二。为什么存在条件变量 首先,举个例子:在应用程序中有连个线 继续阅读 >>


董恒毅 16/08/04 15:58:28
这几天看了一点进程的知识,也会创建一个或几个子进程了,在这里,我很想和大家分享一下,在创建子进程的时候,我们现在所说的写时拷贝技术。 我们知道,在我们fork一个进程之后,系统就会给我们创建一个子进程,此时,子进程会继承父进程几乎所有的资源,并且系统会给子进程分配一个新的物理空间,但实际上,子进程和父进程是用的同一个代码段的,在fork之后子进程只是复制了父进程的数据段,堆栈段,但即使这样,也还是会浪费系统的资源空间,之后,fork做了这样的改变,父进程在fork完之后,子进程只是有了自己的独立虚拟空间,它的物理空间其实是和父进程共享的,当系统检测到父进程和子进程的相应段发生变化的时候,也就是有写的操作的时候,系统才给子进程分配相应的物理空间。 我们也许会问,为什么有写时拷贝这样的技术,这样做的用处是什么,你可以想想,当我们fork一个程序之后,如果立马使用了exec函数族,那么如果还像以前那样,fork完之后就复制父进程的资源给子进程,但是子进程根本用不到这些代码和数据,那么系统的资源就会被浪费,unix和unix(like)是非常讲究效率的操作 继续阅读 >>


董恒毅 16/08/01 21:00:55
等待进程结束 当子进程先于父进程退出时,如果父进程没有调用wait和waitpid函数,子进程就会进入僵尸状态 #include<sys/types.h> #include<sys/wait.h> pid_t wait(int *statloc) pid_t waitpid(pid_t pid, int *statloc, int options) //wait函数的返回值是终止运行的子进程的pid,参数statloc存放的是子进程的退出码,状态信息将被写入statloc所指向的变量 //wait函数也会来等待子进程的结束,但它用于等待某个特定的子进程的pid,statloc和wait的含义相同,option如果被设置为WNOHANG,则父进程不被挂起而立即执行后面的代码 如果想让父进程周期性的检查某个特定子进程是否退出,可以写如下代码: waitpid(child pid, (int *)0, WNOHANG) 如果子进程未退出则返回0,子进程已经结束,返回childpid,失败返回-1 进程的其他操作 继续阅读 >>


董恒毅 16/08/01 17:41:39