首页 技术 正文
技术 2022年11月14日
0 收藏 527 点赞 3,859 浏览 3094 个字

1. Unix IPC(InterProcess Communication)

同一主机的各个进程间的IPC:管道、FIFO、消息队列、信号量、共享存储器

不同主机上的各个进程间IPC:socket套接字 

2. 管道

管道进行IPC有两个局限:(1) 半双工,即数据只能在一个方向上流动(2) 只能在具有公共祖先的进程之间使用。通常,一个管道由一个进程创建,然后该进程调用fork,此后 父子进程之间可以使用该管道 fstat函数对管道的每一端都返回一个FIFO类型的文件描述符,可以用S_ISFIFO宏来测试管道 通常是一个进程调用pipe函数创建管道,紧接着调用fork,这样就创建了从父进程到子进程的IPC通道APUE 学习笔记(十)  高级I/O 对于从父进程到子进程的管道,父进程关闭 管道的读端(fd[0])子进程关闭管道的写端(fd[1])APUE 学习笔记(十)  高级I/O popen、pclose两个函数实现的操作是:创建一个管道,调用fork产生一个子进程,关闭管道的不使用端,执行一个shell以运行命令,最后等待命令终止 

#include <stdio.h>FILE* popen(const char* cmdstring, const char* type);
int pclose(FILE* fp);

函数popen先执行fork,然后调用exec以执行cmdstring,并且返回一个标准I/O文件指针

APUE 学习笔记(十)  高级I/O

APUE 学习笔记(十)  高级I/O

type为“r”表示可读,为“w”表示可写 简单实现一个popen:

 #include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/wait.h>
#include <fcntl.h> /* pointer to array allocated at run-time */
static pid_t* childpid = NULL; /* from our open_max() */
static int maxfd; FILE* my_popen(const char* cmdstring, const char* type)
{
int pfd[];
pid_t pid; /* only allow type = "r" or "w" */
if ((type[] != 'r' && type[] != 'w') || type[] != ) {
errno = EINVAL;
return NULL;
}
childpid = (pid_t*)calloc(maxfd, sizeof(pid_t));
if (childpid == NULL) {
return NULL;
}
} if (pipe(pfd) < ) {
return NULL;
} if ((pid = fork()) < ) {
return NULL;
} else if (pid == ) { /* child */
if (*type == 'r') {
close(pfd[]);
if (pfd[] != STDOUT_FILENO) {
dup2(pfd[], STDOUT_FILENO);
close(pfd[]);
}
} else {
close(pfd[]);
if (pfd[] != STDIN_FILENO) {
dup2(pfd[], STDIN_FILENO);
close(pfd[]);
}
} /* close all fds in childpid[] */
for (int i = ; i < maxfd; ++i) {
if (childpid[i] > ) {
close(i);
}
} } /* parent continue */
FILE* fp;
if (*type == 'r') {
close(pfd[]);
if ((fp = fdopen(pfd[], type)) == NULL) {
return NULL;
}
} else {
close(pfd[]);
if ((fp = fdopen(pfd[], type)) == NULL) {
return NULL;
close(pfd[]);
if ((fp = fdopen(pfd[], type)) == NULL) {
return NULL;
}
} childpid[fileno(fp)] = pid;
return fp;
}

 

3. 消息队列

消息队列是消息的链接表,存放在内核中并由消息队列ID标识msgget用于创建一个新队列或打开一个现存的队列msgsnd将新消息添加到队列尾端msgrcv用户从队列中取消息 

4. 信号量

信号量是一个计数器,用于多进程对共享数据对象的访问 

5. 共享存储器

共享存储器允许多个进程共享一个给定的存储区,因为数据不需要在客户进程和服务器进程之间复制,所以这是最快的IPC使用共享存储区时必须确保 多个进程之间对给定的存储区的同步访问,通常,信号量被用来实现对共享存储区的同步访问

#include <sys/shm.h>
/* 获得共享存储标识符 */
int shmget(key_t key, size_t size, int flag);/* 对共享存储区执行多种操作 */
int shmctl(int shmid, int cmd, struct shmid_ds* buf);/* 进程将共享存储区连接到它的地址空间中 */
void* shmat(int shmid, const void* addr, int flag);

如果addr为0,则此段连接到内核选择的第一个可用地址上。一般将addr指定为0,以便由内核选择地址

打印各种不同类型的数据所存放的位置:

 #include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h> #define ARRAY_SIZE 40000
#define MALLOC_SIZE 100000
#define SHM_SIZE 100000
#define SHM_MODE 0600 /* user read/write */ char array[ARRAY_SIZE]; /* uninitialized data = bss */ int main(int argc, char* argv[])
{
int shmid;
char* ptr = NULL;
char* shmptr = NULL; fprintf(stdout, "array[] from %p to %p\n", array, array + ARRAY_SIZE);
fprintf(stdout, "stack around %p\n", &shmid);
ptr = (char*)malloc(MALLOC_SIZE);
if (ptr == NULL) {
fprintf(stderr, "malloc error\n");
} fprintf(stdout, "malloc from %p to %p\n", ptr, ptr + MALLOC_SIZE); shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE);
if (shmid < ) {
fprintf(stderr, "shmget error\n");
} shmptr = shmat(shmid, , );
if (shmptr == (void*)-) {
fprintf(stderr, "shmat error\n");
} fprintf(stdout, "shared memory from %p to %p\n", shmptr, shmptr + SHM_SIZE);
if (shmctl(shmid, IPC_RMID, ) < ) {
fprintf(stderr, "shmctl error\n");
}
free(ptr);
return ;
}

在基于Intel的Linux系统上运行此程序,其输出如下:

APUE 学习笔记(十)  高级I/O

APUE 学习笔记(十)  高级I/O

如果mmap函数指定了 MAP_SHARED标志,则此存储映射区可被多个进程共享匿名存储映射:调用mmap时指定MAP_ANON标志,并将文件描述符指定为-1,结果得到的映射区域是匿名的,因为并不与一个文件描述符相关联

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,489
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,904
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,737
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,490
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,128
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,291