IPC进程通信

这两天学习的东西有点多,感觉完全应付不过来了 ,一直在消化这几天学习的东西所以2号、3号、4号的学习内容没有及时总结,在此表示深深的愧疚,今天把这些天学习的知识点汇总一下。

主要学习了IPC进程间通信,目前我所理解的IPC主要包括管道、共享内存、信号量。

总结IPC前先复习一下多进程:

一、进程创建:

1、system函数

通过调用shell程序/bin/sh –c来执行string所指定的命令,该函数在内部是通过调用execve(“/bin/sh”,..)函数来实现的。通过system创建子进程后,原进程和子进程各自运行,相互间关联较少。如果system调用成功,将返回0。

2、fork函数

在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。它和其他函数的区别在于:它执行一次返回两个值。其中父进程的返回值是子进程的进程号,而子进程的返回值为0.若出错则返回-1.因此可以通过返回值来判断是父进程还是子进程。

fork函数创建子进程的过程为:使用fork函数得到的子进程是父进程的一个复制品,它从父进程继承了进程的地址空间,包括进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设定、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端,而子进程所独有的只有它的进程号、资源使用和计时器等。通过这种复制方式创建出子进程后,原有进程和子进程都从函数fork返回,各自继续往下运行,但是原进程的fork返回值与子进程的fork返回值不同,在原进程中,fork返回子进程的pid,而在子进程中,fork返回0,如果fork返回负值,表示创建子进程失败。(vfork函数)

3、exec函数族

exec*由一组函数组成

int execl(const char *path, const char *arg, ...)

exec函数族的工作过程与fork完全不同,fork是在复制一份原进程,而exec函数是用exec的第一个参数指定的程序覆盖现有进程空间(也就是说执行exec族函数之后,它后面的所有代码不在执行)。

path是包括执行文件名的全路径名

arg是可执行文件的命令行参数,多个用,分割注意最后一个参数必须为NULL。

二、共享内存与信号量

共享内存机制主要用到 shmget shmat shmdt shmctl 函数;

原理及实现:system V IPC机制下的共享内存本质是一段特殊的内存区域,进程间需要共享的数据被放在该共享内存区域中,所有需要访问该共享区域的进程都要把该共享区域映射到本进程的地址空间中去。这样一个使用共享内存的进程可以将信息写入该空间,而另一个使用共享内存的进程又可以通过简单的内存读操作获取刚才写入的信息,使得两个不同进程之间进行了一次信息交换,从而实现进程间的通信。共享内存允许一个或多个进程通过同时出现在它们的虚拟地址空间的内存进行通信,而这块虚拟内存的页面被每个共享进程的页表条目所引用,同时并不需要在所有进程的虚拟内存都有相同的地址。进程对象对于共享内存的访问通过key(键)来控制,同时通过key进行访问权限的检查。

shmget 通过关键字建立共享内存;

shmat  返回共享内存地址

shmdt  断开与共享内存的链接

Shmctl 回收共享内存

三、IPC进程通信的应用:select多进程服务器

头文件:

#ifndef __CLINET_H__

#define __CLINET_H__

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<unistd.h>

#include<sys/types.h>

#include<sys/ipc.h>

#include<sys/shm.h>

#include<sys/sem.h>

typedef struct tag

{

int m_flag ;

char m_buf[1024] ;

}MBUF, *pMBUF;

void P(int semid) ;

void V(int semid);

#endif

客户端输入端:

/*************************************************************************

> File Name: client_in.c

> Author: Comst

> Mail:[email protected]

> Created Time: Wed 04 Feb 2015 03:04:39 PM CST

************************************************************************/

#include "client.h"

#include<sys/stat.h>

#include<sys/types.h>

#include<sys/fcntl.h>

#define PATH "/home/comst/pipe"

#define SERVER "server.fifo"

int main(int argc, char* argv[])//shm_key sem_key

{

char server_name[128]= "" ;

char read_file[128], write_file[128] ;

char msg[32] ="" ;

int fd_r, fd_w ;

sprintf(server_name, "%s/%s", PATH, SERVER);

int fd_server = open(server_name, O_WRONLY);

memset(read_file, 0, 128);

memset(write_file, 0, 128);

sprintf(read_file, "%s/%d_r.fifo", PATH, getpid());

sprintf(write_file, "%s/%d_w.fifo", PATH, getpid());

mkfifo(read_file, 0666);

mkfifo(write_file, 0666);

sprintf(msg, "%d\n", getpid());

write(fd_server, msg, strlen(msg));

fd_r = open(read_file, O_RDONLY);

fd_w = open(write_file, O_WRONLY);

key_t shm_key, sem_key ;

int my_shm, my_sem ;

char line[1024] ;

pMBUF p ;

shm_key = (key_t)atoi(argv[1]);

sem_key = (key_t)atoi(argv[2]);

my_shm = shmget(shm_key, sizeof(MBUF), 0666|IPC_CREAT);

my_sem = semget(sem_key, 1, 0666 | IPC_CREAT);

semctl(my_sem, 0, SETVAL, 1);

p = (pMBUF)shmat(my_shm, NULL, 0);

memset(p, 0, sizeof(MBUF));

while(memset(line, 0, 1024), fgets(line, 1024, stdin) != NULL)

{

write(fd_w, line, strlen(line));

memset(line, 0, 1024);

read(fd_r, line, 1024);

while( P(my_sem), p -> m_flag == 1)

{

V(my_sem);

sleep(1);

}

strcpy(p ->m_buf, line);

p ->m_flag = 1 ;

V(my_sem);

}

while( P(my_sem), p -> m_flag == 1)

{

V(my_sem);

sleep(1);

}

strcpy(p ->m_buf, "over");

p ->m_flag = 1 ;

V(my_sem);

sleep(3);

shmdt(p);

shmctl(my_shm, IPC_RMID, NULL) ;

semctl(my_sem, 0, IPC_RMID);

}

客户端输出端:

/*************************************************************************

> File Name: client_out.c

> Author: Comst

> Mail:[email protected]

> Created Time: Wed 04 Feb 2015 03:04:39 PM CST

************************************************************************/

#include "client.h"

int main(int argc, char* argv[])//shm_key sem_key

{

key_t shm_key, sem_key ;

int my_shm, my_sem ;

char line[1024] ;

pMBUF p ;

shm_key = atoi(argv[1]);

sem_key = atoi(argv[2]);

my_shm = shmget(shm_key, sizeof(MBUF), 0666);

my_sem = semget(sem_key, 1, 0666 );

semctl(my_sem, 0, SETVAL, 1);

p = (pMBUF)shmat(my_shm, NULL, 0);

memset(p, 0, sizeof(MBUF));

while(1)

{

while(P(my_sem), p -> m_flag == 0)

{

V(my_sem);

sleep(1);

}

printf("%d :  %s\n", getpid(), p -> m_buf);

if(strcmp(p ->m_buf, "over") == 0)

{

V(my_sem);

break ;

}

p -> m_flag = 0 ;

V(my_sem);

}

shmdt(p);

}

功能函数:

/*************************************************************************

> File Name: ./func.c

> Author: Comst

> Mail:[email protected]

> Created Time: Wed 04 Feb 2015 03:17:06 PM CST

************************************************************************/

#include "client.h"

void P(int semid)

{

struct sembuf my_buf ;

memset(&my_buf, 0, sizeof(my_buf) );

my_buf.sem_num = 0 ;

my_buf.sem_op = -1 ;

my_buf.sem_flg = SEM_UNDO ;

semop(semid, &my_buf, 1);

}

void V(int semid)

{

struct sembuf my_buf ;

memset(&my_buf, 0, sizeof(my_buf) );

my_buf.sem_num = 0 ;

my_buf.sem_op = 1 ;

my_buf.sem_flg = SEM_UNDO ;

semop(semid, &my_buf, 1);

}

服务器:

/*************************************************************************

> File Name: server.c

> Author: Comst

> Mail:[email protected]

> Created Time: Wed 04 Feb 2015 04:40:58 PM CST

************************************************************************/

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<unistd.h>

#include<sys/stat.h>

#include<sys/types.h>

#include<fcntl.h>

#include<signal.h>

#define PATH "/home/comst/pipe"

#define NAME "server.fifo"

void child_handle(int sig_num)

{

printf("a child exit!\n");

wait(NULL);

}

void reverse(char* str)

{

int bg, end ;

char tmp ;

bg = 0 ;

end = strlen(str) - 1 ;

while(bg < end)

{

tmp = str[bg] ;

str[bg] = str[end] ;

str[end] = tmp ;

bg ++ ;

end -- ;

}

}

void child_main(int fd_rd, int fd_wr)

{

char buf[1024] ;

while(memset(buf, 0, 1024), read(fd_rd, buf, 1024) != 0)

{

reverse(buf);

write(fd_wr, buf, strlen(buf));

}

}

int main(int argc, char* argv[])

{

signal(17, child_handle);

char file_name[128]  = "";

char client_r[128], client_w[128];

char line[32] ;

int fd_read ;

int client_id ;

int fd_cr , fd_cw ;

FILE* fp ;

sprintf(file_name, "%s/%s", PATH, NAME);

mkfifo(file_name, 0666) ;

fd_read = open(file_name, O_RDONLY);

open(file_name, O_WRONLY);

fp = fdopen(fd_read, "r");

while(memset(line, 0 , 32), fgets(line, 32, fp) != NULL)// "pid\n"

{// cr  cw pid_r.fifo  pid_w.fifo

sscanf(line, "%d", &client_id);

printf("client: %d request !\n", client_id) ;

memset(client_r, 0, 128);

memset(client_w, 0, 128);

sprintf(client_r, "%s/%d_r.fifo", PATH, client_id);

sprintf(client_w, "%s/%d_w.fifo", PATH, client_id);

fd_cw = open(client_r, O_WRONLY);

fd_cr = open(client_w, O_RDONLY);

if(fork() == 0)

{

child_main(fd_cr, fd_cw);

close(fd_cr);

close(fd_cw);

exit(1);

}

close(fd_cr);

close(fd_cw);

}

memset(file_name, 0, 128);

sprintf(file_name, "%s/%s", PATH, NAME);

unlink(file_name);

return 0 ;

}

时间: 2024-10-11 22:15:45

IPC进程通信的相关文章

Android 之 IPC 进程通信全解析

Android 之 IPC 进程通信全解析 本篇博客的框架 什么是IPC IPC(Inter-Process Communication) 进程间通信,是指两个不同进程之间数据交换的过程. 在明确其之前,需要先搞懂几个概念: 线程:CPU可调度的最小单位,是程序执行流的最小单元:线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源. 进程: 一个执行单元,在PC 和移动设备上一

IPC进程之间通信的几种方式

概念 进程间通信就是在不同进程之间传播或交换信息,那么不同进程之间存在着什么双方都可以访问的介质呢?进程的用户空间是互相独立的,一般而言是不能互相访问的,唯一的例外是 共享内存区 .但是,系统空间却是“公共场所”,所以内核显然可以提供这样的条件. 除此以外,那就是双方都可以访问的 外设 了.在这个意义上,两个进程当然也可以通过磁盘上的普通文件交换信息,或者通过“注册表”或其它数据库中的某些表项和记录交换信息.广义上这也是进程间通信的手段,但是一般都不把这算作“进程间通信”.因为那些通信手段的效率

操作系统:进程通信(IPC)

进程通信:进程间的信息交换. 进程是分配系统资源的单位,因此各进程拥有的内存地址空间相互独立. 为了保证安全,一个进程不能直接访问另一个进程的地址空间. 为了保证进程间的安全通信,操作系统提供了一些方法. 管道 管道:指用于连接读写进程的一个共享文件,又名pipe文件.其实就是在内存中开辟的一个大小固定的缓冲区. 命名管道(FIFO) 它是一种文件类型. FIFO可以在无关进程之间交换数据. FIFO以一种特殊设备文件形式存在于文件系统中. FIFO的通信方式类似于在进程中使用文件来传输数据,只

第七课 进程通信

unix_c_07.txt================第七课 进程通信================一.基本概念------------1. 何为进程间通信~~~~~~~~~~~~~~~~~进程间通信(Interprocess Communication, IPC)是指两个,或多个进程之间进行数据交换的过程.2. 进程间通信分类~~~~~~~~~~~~~~~~~1) 简单进程间通信:命令行参数.环境变量.信号.文件.2) 传统进程间通信:管道(fifo/pipe).3) XSI进程间通信:

android 远程Service以及AIDL的跨进程通信

在Android中,Service是运行在主线程中的,如果在Service中处理一些耗时的操作,就会导致程序出现ANR. 但如果将本地的Service转换成一个远程的Service,就不会出现这样的问题了. 转换成远程Service非常简单,只需要在注册Service的时候将他的android:process的属性制定成 :remote就可以了. 重新运行项目,你会发现,不会出现ANR了. 为什么将MyService转换成远程Service后就不会导致程序ANR了呢?这是由于,使用了远程Serv

进程通信之内存共享篇

进程通信之_ 内存共享 概念:共享内存是被多个进程共享的一部分物理内存.共享内存是进程间的共享数最快的方法,一个进程向共享内存区域写入数据,共享这个内存区域的所有进程就可以写入数据,所有进程就可以立刻看到其中的内容. 实现步骤;1.创建共享内存,使用shmget函数2.映射共享内存,将这段创建的共享内存映射到具体的进程空间去,使用shmat函数 创建:int shmget (key_t key,int size,int shmflg)key 标识内存功效的键值0/ipc_private.成功返回

进程通信之共享内存

共享内存 共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样.而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程. 共享内存并未提供同步机制,也就是说,在第一个进程结束对共享内存的写操作之前,并无自

进程通信和线程通信

Linux系统中的线程通信方式主要以下几种: *  锁机制:包括互斥锁.条件变量.读写锁 进程通信: 管道(PIPE):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系(父子进程)的进程间使用.另外管道传送的是无格式的字节流,并且管道缓冲区的大小是有限的(管道缓冲区存在于内存中,在管道创建时,为缓冲区分配一个页面大小). 有名管道 (FIFO): 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信. 信号(Signal): 信号是一种比较复杂的通信方式,用于通知接

Android 进程通信机制之 AIDL

什么是 AIDL AIDL 全称 Android Interface Definition Language,即 安卓接口描述语言.听起来很深奥,其实它的本质就是生成进程间通信接口的辅助工具.它的存在形式是一种 .aidl 文件,开发者需要做的就是在该文件中定义进程间通信的接口,编译的时候 IDE 就会根据我们的 .aidl 接口文件生成可供项目使用的 .java 文件,这和我们说的"语法糖"有些类似. AIDL 的语法就是 java 的语法,就是导包上有点细微差别.java 中如果两