进程间通信的六种方式

本文详细介绍了进程间通信的几种方式,包括匿名/命名管道、消息队列、共享内存、信号量以及信号,以及如何通过Socket进行跨主机通信,展示了各种方法的特点和应用场景。
摘要由CSDN通过智能技术生成

每个进程的用户地址空间都是独立的,一般而言是不能互相访问的,但内核空间是每个进程都共享的,所以进程之间要通信必须通过内核

一、管道

匿名管道通过 fork() 系统调用创建的子进程与父进程之间的通信通道,另外还可以通过以下操作实现非父子进程之间的通信

cat xxx | wc -l

命名管道是一种特殊类型的文件,它允许进程之间进行通信。与匿名管道不同,命名管道在文件系统中有一个相关的路径名,因此允许不相关的进程通过该路径名进行通信

mkfifo my_pipe
echo "Hello, this is a message from the writer!" > my_pipe
cat < my_pipe

特点:

1. 一次性通信: 管道通常用于一次性的通信,一旦数据被读取,它们就会被丢弃。

2. 单向通信: 管道是单向的,不能直接支持双向通信,需要建立多个管道来实现双向通信。

二、消息队列

消息队列是一种进程间通信的方式,允许不同进程之间通过在共享的消息队列中发送和接收消息来进行通信。消息队列允许进程异步地进行通信,即发送方将消息放入队列后即可继续执行,而不需要等待接收方立即接收消息。

特点

1. 异步通信: 发送方和接收方可以以异步的方式进行通信,不需要即时的相互等待。

2. 消息队列不适合比较大数据的传输,因为在内核中每个消息体都有一个最大长度的限制

3. 消息队列通信过程中,存在用户态与内核态之间的数据拷贝开销

三、共享内存

共享内存的机制,就是拿出一块虚拟地址空间来,映射到相同的物理内存中。这样这个进程写入的东西,另外一个进程马上就能看到了,都不需要拷贝来拷贝去,传来传去,大大提高了进程间通信的速度。

四、信号量

信号量是一种用于进程同步和互斥的机制,它允许多个进程之间通过对共享的信号量进行操作来实现对共享资源的访问控制。信号量通常用于解决多个进程竞争共享资源的并发访问问题,可以保证多个进程之间的数据一致性和正确性。

信号量通常具有两种操作:

1. P(等待)操作: 这个操作会将信号量减一,相减后信号量如果小于0,则表示资源已经被占用了,进程需要阻塞等待;如果大于等于0,则说明还有资源可用,进程可以正常执行。

2. V(释放)操作: 这个操作会将信号量加一,相加后信号量如果小于等于0,则表明当前有进程阻塞,于是会将该进程唤醒;如果大于0,则表示当前没有阻塞的进程。

信号量通常与其他进程间通信机制(如共享内存)结合使用,以实现对共享资源的互斥访问和同步操作。使用信号量可以避免进程之间竞争共享资源而导致的数据不一致或错误。

五、信号

信号通常由操作系统或进程内部的异常处理机制发送,可以用于处理如下事件:

1.外部事件: 例如用户按下Ctrl+C中断键,操作系统会向前台进程发送一个 SIGINT 信号,通知进程终止执行。

2.内部事件: 例如某个进程访问了非法内存地址,操作系统会向该进程发送一个 SIGSEGV 信号,通知进程出现了段错误。

3.其他进程的请求: 一个进程可以通过系统调用(如 kill 函数)向另一个进程发送信号。

六、Socket

前面提到的管道、消息队列、共享内存、信号量和信号都是在同一台主机上进行进程间通信,那要想跨网络与不同主机上的进程之间通信,就需要 Socket 通信了。

实际上,Socket 通信不仅可以跨网络与不同主机的进程间通信,还可以在同主机上进程间通信。

根据创建 socket 类型的不同,通信的方式也就不同:

1. 实现 TCP 字节流通信: socket 类型是 AF_INET 和 SOCK_STREAM;
2. 实现 UDP 数据报通信:socket 类型是 AF_INET 和 SOCK_DGRAM;
3. 实现本地进程间通信: 「本地字节流 socket 」类型是 AF_LOCAL 和 SOCK_STREAM,「本地数据报 socket 」类型是 AF_LOCAL 和 SOCK_DGRAM。另外,AF_UNIX 和 AF_LOCAL 是等价的,所以 AF_UNIX 也属于本地 socket;

  • 43
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AIDL(Android Interface Definition Language)是一种用于 Android 平台的接口定义语言,它可以帮助不同进程的组件进行通信。下面是使用 AIDL 进行进程通信的步骤: 1.定义 AIDL 接口 首先,在服务端和客户端之定义一个 AIDL 接口。在 AIDL 文件中,定义需要向客户端公开的方法和参数。 2.实现 AIDL 接口 在服务端中,实现定义的 AIDL 接口,并在 onCreate() 方法中将其注册到系统中。 3.绑定服务端 在客户端中,使用 bindService() 方法绑定服务端。 4.获取 AIDL 接口实例 在客户端中,实现 ServiceConnection 接口,当服务端连接成功时,会回调 onServiceConnected() 方法。在此方法中,可以获取到 AIDL 接口实例。 5.调用 AIDL 接口方法 在客户端中,通过获取到的 AIDL 接口实例,即可调用服务端暴露的方法。 下面是一个简单的示例代码: 服务端: ``` //定义 AIDL 接口 interface IMyAidlInterface { int add(int a, int b); } //实现 AIDL 接口 class MyAidlInterfaceImpl extends IMyAidlInterface.Stub { @Override public int add(int a, int b) throws RemoteException { return a + b; } } //在 onCreate() 方法中注册 AIDL 接口 @Override public void onCreate() { super.onCreate(); Intent intent = new Intent(this, MyAidlInterfaceService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); Log.i(TAG, "MyAidlInterfaceService is created."); } //定义 ServiceConnection 对象,以便在客户端连接时获取 AIDL 接口实例 private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); Log.i(TAG, "MyAidlInterfaceService is connected."); } @Override public void onServiceDisconnected(ComponentName name) { mIMyAidlInterface = null; Log.i(TAG, "MyAidlInterfaceService is disconnected."); } }; ``` 客户端: ``` //定义 ServiceConnection 对象 private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { //获取 AIDL 接口实例 mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); Log.i(TAG, "MyAidlInterfaceService is connected."); } @Override public void onServiceDisconnected(ComponentName name) { mIMyAidlInterface = null; Log.i(TAG, "MyAidlInterfaceService is disconnected."); } }; //使用 bindService() 方法绑定服务端 Intent intent = new Intent(); intent.setComponent(new ComponentName("com.example.myaidlservice", "com.example.myaidlservice.MyAidlInterfaceService")); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); //调用服务端暴露的方法 int result = mIMyAidlInterface.add(1, 2); ``` 希望这个简单的示例可以帮助你了解如何使用 AIDL 进行进程通信

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值