`

linux进程通讯————共享内存

阅读更多

转自:http://blog.csdn.net/anonymalias/article/details/9938865

前面已经讨论过Linux下个各种进程间的通信方式:管道,FIFO,消息队列,他们的共同特点就是通过内核来进行通信(假设POSIX消息队列也是在内核中实现的,因为POSIX标准并没有限定它的实现方式)。向管道,FIFO,消息队列写入数据需要把数据从进程复制到内核,从这些IPC读取数据的时候又需要把数据从内核复制到进程。所以这种IPC方式往往需要2次在进程和内核之间进行数据的复制,即进程间的通信必须借助内核来传递。如下图所示:

通过内核进行通信的IPC

共享内存也是一种IPC,它是目前可用IPC中最快的,它是使用方式是将同一个内存区映射到共享它的不同进程的地址空间中,这样这些进程间的通信就不再需要通过内核,只需对该共享的内存区域进程操作就可以了,和其他IPC不同的是,共享内存的使用需要用户自己进行同步操作。下图是共享内存区IPC的通信,

共享内存IPC通信

1 mmap系列函数简介

mmap函数主要的功能就是将文件或设备映射到调用进程的地址空间中,当使用mmap映射文件到进程后,就可以直接操作这段虚拟地址进行文件的读写等操作,不必再调用readwrite等系统调用。在很大程度上提高了系统的效率和代码的简洁性。

使用mmap函数的主要目的是:

  • 对普通文件提供内存映射I/O,可以提供无亲缘进程间的通信;
  • 提供匿名内存映射,以供亲缘进程间进行通信。
  •  对shm_open创建的POSIX共享内存区对象进程内存映射,以供无亲缘进程间进行通信。

下面是mmap函数的接口以及说明:

 

[cpp] view plaincopy
 
  1. #include <sys/mman.h>  
  2. void *mmap(void *start, size_t len, int prot, int flags, int fd, off_t offset);  
  3.                //成功返回映射到进程地址空间的起始地址,失败返回MAP_FAILED  

 

start:指定描述符fd应被映射到的进程地址空间内的起始地址,它通常被设置为空指针NULL,这告诉内核自动选择起始地址,该函数的返回值即为fd映射到内存区的起始地址。

len:映射到进程地址空间的字节数,它从被映射文件开头的第offset个字节处开始,offset通常被设置为0。如下图是内存映射文件的一个例子:

内存映射文件的示例

prot:内存映射区的保护由该参数来设定,通常由以下几个值组合而成:

  • PROT_READ:数据可读;
  •  PROT_WRITE:数据可写;
  •  PROT_EXEC:数据可执行;
  •  PROT_NONE:数据不可访问;

flags:设置内存映射区的类型标志,POSIX标志定义了以下三个标志:

  • MAP_SHARED:该标志表示,调用进程对被映射内存区的数据所做的修改对于共享该内存区的所有进程都可见,而且确实改变其底层的支撑对象(一个文件对象或是一个共享内存区对象)。
  •  MAP_PRIVATE:调用进程对被映射内存区的数据所做的修改只对该进程可见,而不改变其底层支撑对象。
  •  MAP_FIXED:该标志表示准确的解释start参数,一般不建议使用该标志,对于可移植的代码,应该把start参数置为NULL,且不指定MAP_FIXED标志。

上面三个标志是在POSIX.1-2001标准中定义的,其中MAP_SHAREDMAP_PRIVATE必须选择一个。在Linux中也定义了一些非标准的标志,例如MAP_ANONYMOUSMAP_ANON),MAP_LOCKED等,具体参考Linux手册。

fd:有效的文件描述符。除非设定了MAP_ANONYMOUSMAP_ANON)标志,在Linux下面会忽略fd参数,而有的系统实现如BSD需要置fd-1

offset:相对文件的起始偏移。

从进程的地址空间中删除一个映射关系,需要用到下面的函数:

 

[cpp] view plaincopy
 
  1. #include <sys/mman.h>  
  2. int munmap(void *start, size_t len);  
  3.                            //成功返回0,出错返回-1  

 

start:被映射到的进程地址空间的内存区的起始地址,即mmap返回的地址。

len:映射区的大小。

对于一个MAP_SHARED的内存映射区,内核的虚拟内存算法会保持内存映射文件和内存映射区的同步,也就是说,对于内存映射文件所对应内存映射区的修改,内核会在稍后的某个时刻更新该内存映射文件。如果我们希望硬盘上的文件内容和内存映射区中的内容实时一致,那么我们就可以调用msync开执行这种同步:

 

[cpp] view plaincopy
 
  1. #include <sys/mman.h>  
  2. int msync(void *start, size_t len, int flags);  
  3.                           //成功返回0,出错返回-1  

 

start:被映射到的进程地址空间的内存区的起始地址,即mmap返回的地址。

len:映射区的大小。

flags:同步标志,有一下三个标志:

  • MS_ASYNC:异步写,一旦写操作由内核排入队列,就立刻返回;
  • MS_SYNC:同步写,要等到写操作完成后才返回。
  •  MS_INVALIDATE:使该文件的其他内存映射的副本全部失效。

2 mmap内存映射区的大小

Linux下的内存是采用页式管理机制。通过mmap进行内存映射,内核生成的映射区的大小都是以页面大小PAGESIZE为单位,即为PAGESIZE的整数倍。如果mmap映射的长度不是页面大小的整数倍,那么多余空间也会被闲置浪费。

下面可以查看Linux的页面大小

 

[cpp] view plaincopy
 
  1. #include <iostream>  
  2. #include <unistd.h>  
  3.   
  4. int main()  
  5. {  
  6.     std::cout<<"page size:"<<sysconf(_SC_PAGE_SIZE)<<std::endl;  
  7.     return 0;  
  8. }  

 

输出结果是:

 

[cpp] view plaincopy
 
  1. page size:4096  

 

那么下面对映射文件的大小和映射长度的不同情况进行讨论。

(1)映射文件的大小和映射长度相同

下面的代码

 

[cpp] view plaincopy
 
  1. #include <iostream>  
  2. #include <cstring>  
  3. #include <cerrno>  
  4.   
  5. #include <unistd.h>  
  6. #include <fcntl.h>  
  7. #include <sys/mman.h>  
  8.   
  9. using namespace std;  
  10.   
  11. #define  PATH_NAME "/tmp/memmap"  
  12.   
  13. int main(int argc, char **argv)  
  14. {  
  15.     int fd;  
  16.   
  17.     fd = open(PATH_NAME, O_RDWR | O_CREAT, 0666);  
  18.     if (fd < 0)  
  19.     {  
  20.         cout<<"open file "<<PATH_NAME<<" failed...";  
  21.         cout<<strerror(errno)<<endl;  
  22.         return -1;  
  23.     }  
  24.   
  25.     if (ftruncate(fd, 5000) < 0)  
  26.     {  
  27.         cout<<"change file size  failed...";  
  28.         cout<<strerror(errno)<<endl;  
  29.           
  30.         close(fd);  
  31.         return -1;  
  32.     }  
  33.   
  34.     char *memPtr;  
  35.   
  36.     memPtr = (char *)mmap(NULL, 5000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  
  37.     close(fd);  
  38.   
  39.     if (memPtr == MAP_FAILED)  
  40.     {  
  41.         cout<<"mmap failed..."<<strerror(errno)<<endl;  
  42.         return -1;  
  43.     }  
  44.   
  45.     cout<<"[0]:"<<(int)memPtr[0]<<endl;  
  46.     cout<<"[4999]:"<<(int)memPtr[4999]<<endl;  
  47.     cout<<"[5000]:"<<(int)memPtr[5000]<<endl;  
  48.     cout<<"[8191]:"<<(int)memPtr[8191]<<endl;  
  49.     cout<<"[8192]:"<<(int)memPtr[8192]<<endl;  
  50.     cout<<"[4096 * 3 - 1]:"<<(int)memPtr[4096 * 3 - 1]<<endl;  
  51.     cout<<"[4096 * 3]:"<<(int)memPtr[4096 * 3]<<endl;  
  52.       
  53.     return 0;  
  54. }  

 

执行结果如下:

 

[cpp] view plaincopy
 
  1. [0]:0  
  2. [4999]:0  
  3. [5000]:0  
  4. [8191]:0  
  5. [8192]:91  
  6. [4096 * 3 - 1]:0  
  7. Segmentation fault  

 

用下图来分析执行结果:

映射文件的大小和映射长度相同

由执行结果可以看到,能够完整的访问到前三页,在访问第四页的时候会产生SIGSEGV信号,发生Segmentation fault段越界访问错误。按照《UNIX 网络编程 卷2:进程间通信》中P257的讲解,内核会为该内存映射两个页面,访问前两个页面不会有问题,但访问第三个页面会产生SIGSEGV错误信号。这个差异具体应该是底层实现有关,留待以后研究

(2)映射文件的大小小于映射长度

在上面代码的基础上,修改mmap内存映射还是部分的第二个参数,如下:

 

[cpp] view plaincopy
 
  1. memPtr = (char *)mmap(NULL, 4096 * 3, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  

 

执行结果如下:

 

[cpp] view plaincopy
 
  1. [0]:0  
  2. [4999]:0  
  3. [5000]:0  
  4. [8191]:0  
  5. Bus error  

 

再修改访问代码,访问偏移4096*3以后的内存映射去,结果的情况是

 

[cpp] view plaincopy
 
  1. [4096 * 3]:91  
  2. [4096 * 4 - 1]:0  
  3. Segmentation fault // memPtr[4096*4]  

 

用下图来分析执行结果:

该执行结果和之前的映射文件大小和映射长度相同的情况有比较大的区别,在访问内存映射区内部但超出底层支撑对象的大小的区域部分会产生SIGBUS错误信息,产生生BUS error错误,但访问第四页不会出问题,访问第四页以后的内存区就会产生 SIGSEGV错误信息。按照《UNIX 网络编程 卷2:进程间通信》中P258的讲解,访问第三个页面以后的内存会产生SIGSEGV错误信号。这个差异具体应该是底层实现有关,留待以后研究

3 mmap实现进程间通信

下面将介绍mmap本身提供的进程间通信的两种方式,分别用于无亲缘和亲缘进程间的通信。

(1)通过匿名内存映射提供亲缘进程间的通信

我们可以通过在父进程fork之前指定MAP_SHARED调用mmap,通过映射一个文件来实现父子进程间的通信,POSIX保证了父子进程的内存映射关系保留到子进程中,父子进程对内存映射去的修改双方都可以看到。

Linux 2.4以后,mmap提供匿名内存映射机制,即将mmapflags参数指定为:MAP_SHARED | MAP_ANON。这样就彻底避免了内存映射文件的创建和打开,简化了对文件的操作。匿名内存映射机制的目的就是为了提供一个穿越父子进程间的内存映射区,很方便的提供了亲缘进程间的通信,下面是测试代码:

 

[cpp] view plaincopy
 
  1. #include <iostream>  
  2. #include <cstring>  
  3. #include <cerrno>  
  4.   
  5. #include <unistd.h>  
  6. #include <fcntl.h>  
  7. #include <sys/mman.h>  
  8.   
  9. using namespace std;  
  10.   
  11. int main(int argc, char **argv)  
  12. {  
  13.     int *memPtr;  
  14.   
  15.     memPtr = (int *) mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, 0, 0);  
  16.     if (memPtr == MAP_FAILED)  
  17.     {  
  18.         cout<<"mmap failed..."<<strerror(errno)<<endl;  
  19.         return -1;  
  20.     }  
  21.   
  22.     *memPtr = 0;  
  23.   
  24.     if (fork() == 0)  
  25.     {  
  26.         *memPtr = 1;  
  27.         cout<<"child:set memory "<<*memPtr<<endl;  
  28.   
  29.         exit(0);  
  30.     }  
  31.   
  32.     sleep(1);  
  33.     cout<<"parent:memory value "<<*memPtr<<endl;  
  34.   
  35.     return 0;  
  36. }  

 

执行结果如下:

 

[cpp] view plaincopy
 
  1. child:set memory 1  
  2. parent:memory value 1  

 

2)通过内存映射文件提供无亲缘进程间的通信

通过在不同进程间对同一内存映射文件进行映射,来进行无亲缘进程间的通信,如下测试代码:

 

[cpp] view plaincopy
 
  1. //process 1  
  2. #include <iostream>  
  3. #include <cstring>  
  4. #include <errno.h>  
  5.   
  6. #include <unistd.h>  
  7. #include <fcntl.h>  
  8. #include <sys/mman.h>  
  9.   
  10. using namespace std;  
  11.   
  12. #define  PATH_NAME "/tmp/memmap"  
  13.   
  14. int main()  
  15. {  
  16.     int *memPtr;  
  17.     int fd;  
  18.   
  19.     fd = open(PATH_NAME, O_RDWR | O_CREAT, 0666);  
  20.     if (fd < 0)  
  21.     {  
  22.         cout<<"open file "<<PATH_NAME<<" failed...";  
  23.         cout<<strerror(errno)<<endl;  
  24.         return -1;  
  25.     }  
  26.   
  27.     ftruncate(fd, sizeof(int));  
  28.   
  29.     memPtr = (int *)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  
  30.     close(fd);  
  31.   
  32.     if (memPtr == MAP_FAILED)  
  33.     {  
  34.         cout<<"mmap failed..."<<strerror(errno)<<endl;  
  35.         return -1;  
  36.     }  
  37.   
  38.     *memPtr = 111;  
  39.     cout<<"process:"<<getpid()<<" send:"<<*memPtr<<endl;  
  40.   
  41.     return 0;  
  42. }  
  43.   
  44. //process 2  
  45. #include <iostream>  
  46. #include <cstring>  
  47. #include <errno.h>  
  48.   
  49. #include <unistd.h>  
  50. #include <fcntl.h>  
  51. #include <sys/mman.h>  
  52.   
  53. using namespace std;  
  54.   
  55. #define  PATH_NAME "/tmp/memmap"  
  56.   
  57. int main()  
  58. {  
  59.     int *memPtr;  
  60.     int fd;  
  61.   
  62.     fd = open(PATH_NAME, O_RDWR | O_CREAT, 0666);  
  63.     if (fd < 0)  
  64.     {  
  65.         cout<<"open file "<<PATH_NAME<<" failed...";  
  66.         cout<<strerror(errno)<<endl;  
  67.         return -1;  
  68.     }  
  69.   
  70.     memPtr = (int *)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  
  71.     close(fd);  
  72.   
  73.     if (memPtr == MAP_FAILED)  
  74.     {  
  75.         cout<<"mmap failed..."<<strerror(errno)<<endl;  
  76.         return -1;  
  77.     }  
  78.   
  79.     cout<<"process:"<<getpid()<<" receive:"<<*memPtr<<endl;  
  80.   
  81.     return 0;  
  82. }  

 

执行结果如下:

 

[cpp] view plaincopy
 
  1. # ./send   
  2. process:12711 send:111  
  3. # ./recv   
  4. process:12712 receive:111  

 

上面的代码都没进行同步操作,在实际的使用过程要考虑到进程间的同步通常会用信号量来进行共享内存的同步

基于mmapPOSIX共享内存

上面介绍了通过内存映射文件进行进程间的通信的方式,现在要介绍的是通过POSIX共享内存区对象进行进程间的通信。POSIX共享内存使用方法有以下两个步骤:

  • 通过shm_open创建或打开一个POSIX共享内存对象;
  • 然后调用mmap将它映射到当前进程的地址空间;

和通过内存映射文件进行通信的使用上差别在于mmap描述符参数获取方式不一样:通过openshm_open。如下图所示:

POSIX共享内存区对象的特殊操作函数就只有创建(打开)和删除两个函数,其他对共享内存区对象的操作都是通过已有的函数进行的。

 

[cpp] view plaincopy
 
  1. #include <sys/mman.h>  
  2. int shm_open(const char *name, int oflag, mode_t mode);  
  3.                               //成功返回非负的描述符,失败返回-1  
  4. int shm_unlink(const char *name);  
  5.                               //成功返回0,失败返回-1  

 

shm_open用于创建一个新的共享内存区对象或打开一个已经存在的共享内存区对象。

namePOSIX IPC的名字,前面关于POSIX进程间通信都已讲过关于POSIX IPC的规则,这里不再赘述。

oflag:操作标志,包含:O_RDONLYO_RDWRO_CREATO_EXCLO_TRUNC。其中O_RDONLYO_RDWR标志必须且仅能存在一项。

mode:用于设置创建的共享内存区对象的权限属性。和open以及其他POSIX IPCxxx_open函数不同的是,该参数必须一直存在,如果oflag参数中没有O_CREAT标志,该位可以置0

shm_unlink用于删除一个共享内存区对象,跟其他文件的unlink以及其他POSIX IPC的删除操作一样,对象的析构会到对该对象的所有引用全部关闭才会发生。

 

POSIX共享内存和POSIX消息队列,有名信号量一样都是具有随内核持续性的特点。

下面是通过POSIX共享内存进行通信的测试代码,代码中通过POSIX信号量来进行进程间的同步操作。

 

[cpp] view plaincopy
 
  1. //process 1  
  2. #include <iostream>  
  3. #include <cstring>  
  4. #include <errno.h>  
  5.   
  6. #include <unistd.h>  
  7. #include <fcntl.h>  
  8. #include <semaphore.h>  
  9. #include <sys/mman.h>  
  10.   
  11. using namespace std;  
  12.   
  13. #define SHM_NAME "/memmap"  
  14. #define SHM_NAME_SEM "/memmap_sem"   
  15.   
  16. char sharedMem[10];  
  17.   
  18. int main()  
  19. {  
  20.     int fd;  
  21.     sem_t *sem;  
  22.   
  23.     fd = shm_open(SHM_NAME, O_RDWR | O_CREAT, 0666);  
  24.     sem = sem_open(SHM_NAME_SEM, O_CREAT, 0666, 0);  
  25.   
  26.     if (fd < 0 || sem == SEM_FAILED)  
  27.     {  
  28.         cout<<"shm_open or sem_open failed...";  
  29.         cout<<strerror(errno)<<endl;  
  30.         return -1;  
  31.     }  
  32.   
  33.     ftruncate(fd, sizeof(sharedMem));  
  34.   
  35.     char *memPtr;  
  36.     memPtr = (char *)mmap(NULL, sizeof(sharedMem), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  
  37.     close(fd);  
  38.   
  39.     char msg[] = "yuki...";  
  40.   
  41.     memmove(memPtr, msg, sizeof(msg));  
  42.     cout<<"process:"<<getpid()<<" send:"<<memPtr<<endl;  
  43.   
  44.     sem_post(sem);  
  45.     sem_close(sem);  
  46.   
  47.     return 0;  
  48. }  
  49.   
  50. //process 2  
  51. #include <iostream>  
  52. #include <cstring>  
  53. #include <errno.h>  
  54.   
  55. #include <unistd.h>  
  56. #include <fcntl.h>  
  57. #include <semaphore.h>  
  58. #include <sys/mman.h>  
  59.   
  60. using namespace std;  
  61.   
  62. #define SHM_NAME "/memmap"  
  63. #define SHM_NAME_SEM "/memmap_sem"   
  64.   
  65. int main()  
  66. {  
  67.     int fd;  
  68.     sem_t *sem;  
  69.   
  70.     fd = shm_open(SHM_NAME, O_RDWR, 0);  
  71.     sem = sem_open(SHM_NAME_SEM, 0);  
  72.   
  73.     if (fd < 0 || sem == SEM_FAILED)  
  74.     {  
  75.         cout<<"shm_open or sem_open failed...";  
  76.         cout<<strerror(errno)<<endl;  
  77.         return -1;  
  78.     }  
  79.   
  80.     struct stat fileStat;  
  81.     fstat(fd, &fileStat);  
  82.   
  83.     char *memPtr;  
  84.     memPtr = (char *)mmap(NULL, fileStat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);  
  85.     close(fd);  
  86.   
  87.     sem_wait(sem);  
  88.   
  89.     cout<<"process:"<<getpid()<<" recv:"<<memPtr<<endl;  
  90.   
  91.     sem_close(sem);  
  92.   
  93.     return 0;  
  94. }  

 

程序的执行结果如下:

 

[cpp] view plaincopy
 
  1. # ./send   
  2. process:13719 send:yuki...  
  3. # ./recv   
  4. process:13720 recv:yuki...  

 

Linux 2.6.18中,对于POSIX信号量和共享内存的名字会在/dev/shm下建立对应的路径名,例如上面的测试代码,会生成如下的路径名:

 

[cpp] view plaincopy
 
  1. # ll /dev/shm/  
  2. total 8  
  3. -rw-r--r-- 1 root root 10 Aug 13 00:28 memmap  
  4. -rw-r--r-- 1 root root 32 Aug 13 00:28 sem.memmap_sem  

 

Aug 13 AM 01:10 @dorm

分享到:
评论

相关推荐

    详解Linux进程间通信——使用共享内存

    共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。这篇文章主要介绍了详解Linux进程间通信——使用共享内存,有兴趣的可以了解一下。

    linux系统进程间通信——共享内存(System V版本)

    之前用过Prosix版本的共享内存和信号量,一直没有实践System V版本的,主要是因为其信号量集的概念操作有些复杂,今天试着写一个SV版本的共享内存进程间通信,使用信号量同步。程序提供了几个简单的用于操作SV版本...

    linux下共享内存+信号量

    linux下共享内存+信号量,不会出奇怪的错误,如信号量和共享内存未清,导致无法再次运行,ctrl+c后能够正常清除信号量及共享内存。

    进程同步——信号量机制

    关于信号量的文章,生产者消费者问题与读者写者问题---信号量机制,PV操作——进程同步的信号量问题,利用信号机制实现的 父子进程同步,嵌入式linux的学习笔记-进程间通信的信号与信号集(四)1)进程的同步与互斥 ...

    Linux进程间通信

    shmget函数 shmat函数 Linux进程间通信——使用共享内存 使用消息队列进行进程间通信

    Linux 下进程间通信实例

    Linux 下进程间通信实例之一——共享内存 使用了信号量用于进程间的同步

    共享内存示例代码

    Linux系统编程——进程间通信:共享内存,相关教程链接如下: http://blog.csdn.net/tennysonsky/article/details/46425485

    linux源代码分析——消息管理

    在操作系统中,有些进程存在着相互制约的关系,这些制约关系来源于并行进程的相互合作和资源共享。...在linux 中支持UNIX SYSTEM V 的三种通信机制: 消息队列, 信号量和共享内存. 现就消息队列这种机制进行分析.

    非常宝贵的LINUX学习笔记

    【linux学习笔记-1】使用GDB调试简单的用户程序 【linux学习笔记-2】父子进程共享文件描述符 【linux学习笔记-3】文件操作(stat,chmod,umask) 【linux学习笔记-4】进程...【linux学习笔记--19】POSIX IPC——共享内存

    边干边学——LINUX内核指导

    6. 4 利用共享内存进行进程间通信 第7章 虚拟存储 7. 1 虚拟内存管理 7. 2 Linux虚拟内存管理 7. 3 实例 第8章 进程的同步 8. 1 同步机制 8. 2 Linux中几种同步机制的实现 8. 3 设计我们自己的同步机制 第9章 进程...

    基于VS2019 C++的跨平台(Linux)开发的项目——360 度智能行车辅助系统

    基于 Socket 网络通讯技术,使用Qt5进行GUI编程,结合OpenCV图像处理,采用Sqlite3数据库,实现的 360 度智能...项目核心技术点 :服务器分离、共享内存设计、线程池、Socket网络编程、进程间通信、epoll多路IO复用等。

    Linux学习笔记Linux学习资料Linux教程

    【linux学习笔记--19】POSIX IPC——共享内存.doc 【linux学习笔记-10】Linux进程相关系统调用(三).doc 【linux学习笔记-11】守护进程daemon.doc 【linux学习笔记-12】守护进程的日志实现.doc 【linux学习笔记-13...

    详解Linux进程间通信——使用信号量

    而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在访问它,也就是说信号量是用来调协进程对共享资源的访问的。 信号量是一个特殊的变量,程序对其访问都是原子操作,且只允许对它进行等待...

    嵌入式Linux C编程入门(第2版) PPT

    10.3.3 共享内存 308 10.3.4 消息队列 309 10.4 arm linux线程相关api 312 10.5 linux守护进程 317 10.5.1 守护进程概述 317 10.5.2 编写规则 318 10.5.3 守护进程实例 319 本章小结 321 ...

    深入Linux内核架构——简介与概述

    纯技术层面上,内核是硬件与软件的之间的一个中间层。作用是将应用程序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备和组件进行寻址...内核负责将可用共享资源分配到各个系统进程,同时保证系统的完整性。

    华清远见嵌入式linux应用程序开发技术详解下载(内部资料).rar

     7.2 Linux进程控制编程   7.3 Linux守护进程   7.4 实验内容   本章小结   思考与练习  第8章 进程间通信   8.1 Linux下进程间通信概述   8.2 管道通信   8.3 信号通信  8.4 共享内存  ...

    嵌入式Linux应用程序开发标准教程(第2版全)

    7.2 Linux进程控制编程 7.3 Linux守护进程 7.3.1 守护进程概述 7.3.2 编写守护进程 7.3.3 守护进程的出错处理 7.4 实验内容 7.4.1 编写多进程程序 7.4.2 编写守护进程 7.5 本章小结 7.6 思考与练习 第8章 进程间...

    Linux内核源代码情景分析 (上下册 高清非扫描 )

    6.7 共享内存 6.8 信号量 第7章基于socket的进程间通信 7.1系统调用socket() 7.2函数sys—socket()——创建插口 7.3函数sys—bind()——指定插口地址 7.4函数sys—listen()——设定server插口 7.5函数sys—...

Global site tag (gtag.js) - Google Analytics