linux进程通信socket
Socket通信创建步骤:
(1)通过socket()函数创建socket
(2)通过bind函数绑定socket于设备地址
(3)进行读写操作read/recv/recvfrom write/send/sendto
(4)close方法关闭套接字
例子如下:
test1.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<netinet/in.h>
#include<arpa/inet.h>
intmain(void)
{
//createsocket
intfd=socket(AF_INET,SOCK_DGRAM,0);
if(fd==-1)
{
perror("socket ");
exit(-1);
}
printf("socketfd=%d ",fd);
//buildconnectionaddress
structsockaddr_inaddr;
addr.sin_family=AF_INET;
addr.sin_port=htons(6666);
addr.sin_addr.s_addr=inet_addr("127.0.0.1");
intr;
r=bind(fd,(structsockaddr*)&addr,sizeof(addr));
if(r==-1)
{
perror("bind");
close(fd);
exit(-1);
}
printf("bindaddresssuccessful! ");
//acceptorsendmessage
charbuf[255];
structsockaddr_infrom;
socklen_tlen;
len=sizeof(from);
while(1)
{
r=recvfrom(fd,buf,sizeof(buf)-1,0,(structsockaddr*)&from,&len);
if(r>0)
{
buf[r]=0;
printf("Themessagefrom%sis:%s ",inet_ntoa(from.sin_addr),buf);
}
else
{
break;
}
}
//closesocket
close(fd);
return0;
}
test2.c
java">#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
intmain(void)
{
//createsocket
intfd=socket(AF_INET,SOCK_DGRAM,0);
if(fd==-1)
{
perror("socket");
exit(-1);
}
printf("createsocketOK! ");
//createansendaddress
structsockaddr_inaddr={};
addr.sin_family=AF_INET;
addr.sin_port=htons(6666);
addr.sin_addr.s_addr=inet_addr("127.0.0.1");
//
intr;
charbuf[255];
while(1)
{
r=read(0,buf,sizeof(buf)-1);
if(r<=0)
break;
sendto(fd,buf,r,0,(structsockaddr*)&addr,sizeof(addr));
}
//closesocket
close(fd);
return0;
}
先运行test1.c,然后运行test2.c,在test2.c运行后输入内容,在test1.c所在终端中就会显示信息
运行结果如下:
❷ Linux 进程间套接字通信(Socket)基础知识
姓名:罗学元 学号:21181214375 学院:广州研究院
【嵌牛导读】Linux进程间套接字通信基础
【嵌牛鼻子】Linux 进程间套接字及通信介绍
【嵌牛提问】Linux进程间套接字包含哪些内容,如何实现通信
一、套接字(Socket)通信原理
套接字通信允许互联的位于不同计算机上的进程之间实现通信功能。
二、套接字的属性
套接字的特性由3个属性确定,它们分别是:域、类型和协议。
1. 套接字的域
它指定套接字通信中使用的网络介质,最常见的套接字域是AF_INET,它指的是Internet网络。当客户使用套接字进行跨网络的连接时,它就需要用到服务器计算机的IP地址和端口来指定一台联网机器上的某个特定服务,所以在使用socket作为通信的终点,服务器应用程序必须在开始通信之前绑定一个端口,服务器在指定的端口等待客户的连接。
另一个域AF_UNIX表示UNIX文件系统,就是文件输入/输出,它的地址就是文件名。
2. 套接字类型
因特网提供了两种通信机制:流(stream)和数据报(datagram),因而套接字的类型也就分为流套接字和数据报套接字。我们主要看流套接字。
流套接字由类型SOCK_STREAM指定,它们是在AF_INET域中通过TCP/IP连接实现,同时也是AF_UNIX中常用的套接字类型。
流套接字提供的是一个有序、可靠、双向字节流的连接,因此发送的数据可以确保不会丢失、重复或乱序到达,而且它还有一定的出错后重新发送的机制。
与流套接字相对的是由类型SOCK_DGRAM指定的数据报套接字,它不需要建立连接和维持一个连接,它们在AF_INET中通常是通过UDP/IP实现的。它对可以发送的数据的长度有限制,数据报作为一个单独的网络消息被传输,它可能丢失、复制或错乱到达,UDP不是一个可靠的协议,但是它的速度比较高,因为它并不需要总是要建立和维持一个连接。
3.套接字协议
只要底层的传输机制允许不止一个协议来提供要求的套接字类型,我们就可以为套接字选择一个特定的协议。通常只需要使用默认值。
三、套接字地址
每个套接字都有其自己的地址格式,对于AF_UNIX域套接字来说,它的地址由结构sockaddr_un来描述,该结构定义在头文件
struct sockaddr_un{
sa_family_t sun_family; //AF_UNIX,它是一个短整型
char sum_path[]; //路径名
};
对于AF_INET域套接字来说,它的地址结构由sockaddr_in来描述,它至少包括以下几个成员:
struct sockaddr_in{
short int sin_family; //AN_INET
unsigned short int sin_port; //端口号
struct in_addr sin_addr; //IP地址
}
而in_addr被定义为:
struct in_addr{
unsigned long int s_addr;
}
四、基于流套接字的客户/服务器的工作流程
使用socket进行进程通信的进程采用的客户/服务器系统是如何工作的呢?
1.服务器端
首先,服务器应用程序用系统调用socket来创建一个套接字,它是系统分配给该服务器进程的类似文件描述符的资源,它不能与其他的进程共享。
接下来,服务器进程会给套接字起个名字,我们使用系统调用bind来给套接字命名。然后服务器进程就开始等待客户连接到这个套接字。
然后,系统调用listen来创建一个队列,并将其用于存放来自客户的进入连接。
最后,服务器通过系统调用accept来接受客户的连接。它会创建一个与原有的命名套接不同的新套接字,这个套接字只用于与这个特定客户端进行通信,而命名套接字(即原先的套接字)则被保留下来继续处理来自其他客户的连接。
2.客户端
基于socket的客户端比服务器端简单。同样,客户应用程序首先调用socket来创建一个未命名的套接字,然后讲服务器的命名套接字作为一个地址来调用connect与服务器建立连接。
一旦连接建立,我们就可以像使用底层的文件描述符那样用套接字来实现双向数据的通信。
❸ 请问linux怎么增大socket连接上限
1、修改用户进程可打开文件数限制
在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,
最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统
为每个TCP连接都要创建一个socket句柄,每个socket句柄同时也是一个文件句柄)。
可使用ulimit命令查看系统允许当前用户进程打开的文件数限制:
[speng@as4 ~]$ ulimit -n
1024
这表示当前用户的每个进程最多允许同时打开1024个文件,这1024个文件中还得除去
每个进程必然打开的标准输入,标准输出,标准错误,服务器监听 socket,
进程间通讯的unix域socket等文件,那么剩下的可用于客户端socket连接的文件数就
只有大概1024-10=1014个左右。也就是说缺省情况下,基于Linux的通讯程序最多允许
同时1014个TCP并发连接。
对于想支持更高数量的TCP并发连接的通讯处理程序,就必须修改Linux对当前用户的
进程同时打开的文件数量的软限制(soft limit)和硬限制(hardlimit)。其中软限制
是指Linux在当前系统能够承受的范围内进一步限制用户同时打开的文件数;硬限制
则是根据系统硬件资源状况(主要是系统内存)计算出来的系统最多可同时打开的文件数量。
通常软限制小于或等于硬限制。
修改上述限制的最简单的办法就是使用ulimit命令:
[speng@as4 ~]$ ulimit -n
上述命令中,在中指定要设置的单一进程允许打开的最大文件数。如果系统回显
类似于“Operation notpermitted”之类的话,说明上述限制修改失败,实际上是
因为在中指定的数值超过了Linux系统对该用户打开文件数的软限制或硬限制。
因此,就需要修改Linux系统对用户的关于打开文件数的软限制和硬限制。
第一步,修改/etc/security/limits.conf文件,在文件中添加如下行:
speng soft nofile 10240
speng hard nofile 10240
其中speng指定了要修改哪个用户的打开文件数限制,可用’*'号表示修改所有用户的限制;
soft或hard指定要修改软限制还是硬限制;10240则指定了想要修改的新的限制值,
即最大打开文件数(请注意软限制值要小于或等于硬限制)。修改完后保存文件。
第二步,修改/etc/pam.d/login文件,在文件中添加如下行:
session required /lib/security/pam_limits.so
这是告诉Linux在用户完成系统登录后,应该调用pam_limits.so模块来设置系统对
该用户可使用的各种资源数量的最大限制(包括用户可打开的最大文件数限制),
而pam_limits.so模块就会从/etc/security/limits.conf文件中读取配置来设置这些限制值。
修改完后保存此文件。
第三步,查看Linux系统级的最大打开文件数限制,使用如下命令:
[speng@as4 ~]$ cat /proc/sys/fs/file-max
12158
这表明这台Linux系统最多允许同时打开(即包含所有用户打开文件数总和)12158个文件,
是Linux系统级硬限制,所有用户级的打开文件数限制都不应超过这个数值。通常这个系统级
硬限制是Linux系统在启动时根据系统硬件资源状况计算出来的最佳的最大同时打开文件数限制,
如果没有特殊需要,不应该修改此限制,除非想为用户级打开文件数限制设置超过此限制的值。
修改此硬限制的方法是修改/etc/rc.local脚本,在脚本中添加如下行:
echo 22158 > /proc/sys/fs/file-max
这是让Linux在启动完成后强行将系统级打开文件数硬限制设置为22158。修改完后保存此文件。
完成上述步骤后重启系统,一般情况下就可以将Linux系统对指定用户的单一进程允许同时
打开的最大文件数限制设为指定的数值。如果重启后用 ulimit-n命令查看用户可打开文件数限制
仍然低于上述步骤中设置的最大值,这可能是因为在用户登录脚本/etc/profile中使用ulimit -n命令
已经将用户可同时打开的文件数做了限制。由于通过ulimit-n修改系统对用户可同时打开文件的
最大数限制时,新修改的值只能小于或等于上次 ulimit-n设置的值,因此想用此命令增大这个
限制值是不可能的。
所以,如果有上述问题存在,就只能去打开/etc/profile脚本文件,
在文件中查找是否使用了ulimit-n限制了用户可同时打开的最大文件数量,如果找到,
则删除这行命令,或者将其设置的值改为合适的值,然后保存文件,用户退出并重新登录系统即可。
通过上述步骤,就为支持高并发TCP连接处理的通讯处理程序解除关于打开文件数量方面的系统限制。
2、修改网络内核对TCP连接的有关限制
在Linux上编写支持高并发TCP连接的客户端通讯处理程序时,有时会发现尽管已经解除了系统
对用户同时打开文件数的限制,但仍会出现并发TCP连接数增加到一定数量时,再也无法成功
建立新的TCP连接的现象。出现这种现在的原因有多种。
第一种原因可能是因为Linux网络内核对本地端口号范围有限制。此时,进一步分析为什么无法
建立TCP连接,会发现问题出在connect()调用返回失败,查看系统错误提示消息是“Can’t assign requestedaddress”。同时,如果在此时用tcpmp工具监视网络,会发现根本没有TCP连接时客户端
发SYN包的网络流量。这些情况说明问题在于本地Linux系统内核中有限制。
其实,问题的根本原因
在于Linux内核的TCP/IP协议实现模块对系统中所有的客户端TCP连接对应的本地端口号的范围
进行了限制(例如,内核限制本地端口号的范围为1024~32768之间)。当系统中某一时刻同时
存在太多的TCP客户端连接时,由于每个TCP客户端连接都要占用一个唯一的本地端口号
(此端口号在系统的本地端口号范围限制中),如果现有的TCP客户端连接已将所有的本地端口号占满,
则此时就无法为新的TCP客户端连接分配一个本地端口号了,因此系统会在这种情况下在connect()
调用中返回失败,并将错误提示消息设为“Can’t assignrequested address”。
有关这些控制
逻辑可以查看Linux内核源代码,以linux2.6内核为例,可以查看tcp_ipv4.c文件中如下函数:
static int tcp_v4_hash_connect(struct sock *sk)
请注意上述函数中对变量sysctl_local_port_range的访问控制。变量sysctl_local_port_range
的初始化则是在tcp.c文件中的如下函数中设置:
void __init tcp_init(void)
内核编译时默认设置的本地端口号范围可能太小,因此需要修改此本地端口范围限制。
第一步,修改/etc/sysctl.conf文件,在文件中添加如下行:
net.ipv4.ip_local_port_range = 1024 65000
这表明将系统对本地端口范围限制设置为1024~65000之间。请注意,本地端口范围的最小值
必须大于或等于1024;而端口范围的最大值则应小于或等于65535。修改完后保存此文件。
第二步,执行sysctl命令:
[speng@as4 ~]$ sysctl -p
如果系统没有错误提示,就表明新的本地端口范围设置成功。如果按上述端口范围进行设置,
则理论上单独一个进程最多可以同时建立60000多个TCP客户端连接。
第二种无法建立TCP连接的原因可能是因为Linux网络内核的IP_TABLE防火墙对最大跟踪的TCP
连接数有限制。此时程序会表现为在 connect()调用中阻塞,如同死机,如果用tcpmp工具监视网络,
也会发现根本没有TCP连接时客户端发SYN包的网络流量。由于 IP_TABLE防火墙在内核中会对
每个TCP连接的状态进行跟踪,跟踪信息将会放在位于内核内存中的conntrackdatabase中,
这个数据库的大小有限,当系统中存在过多的TCP连接时,数据库容量不足,IP_TABLE无法为
新的TCP连接建立跟踪信息,于是表现为在connect()调用中阻塞。此时就必须修改内核对最大跟踪
的TCP连接数的限制,方法同修改内核对本地端口号范围的限制是类似的:
第一步,修改/etc/sysctl.conf文件,在文件中添加如下行:
net.ipv4.ip_conntrack_max = 10240
这表明将系统对最大跟踪的TCP连接数限制设置为10240。请注意,此限制值要尽量小,
以节省对内核内存的占用。
第二步,执行sysctl命令:
[speng@as4 ~]$ sysctl -p
如果系统没有错误提示,就表明系统对新的最大跟踪的TCP连接数限制修改成功。
如果按上述参数进行设置,则理论上单独一个进程最多可以同时建立10000多个TCP客户端连接。
3、使用支持高并发网络I/O的编程技术
在Linux上编写高并发TCP连接应用程序时,必须使用合适的网络I/O技术和I/O事件分派机制。
可用的I/O技术有同步I/O,非阻塞式同步I/O(也称反应式I/O),以及异步I/O。在高TCP并发的情形下,
如果使用同步I/O,这会严重阻塞程序的运转,除非为每个TCP连接的I/O创建一个线程。
但是,过多的线程又会因系统对线程的调度造成巨大开销。因此,在高TCP并发的情形下使用
同步 I/O是不可取的,这时可以考虑使用非阻塞式同步I/O或异步I/O。非阻塞式同步I/O的技术包括使用select(),poll(),epoll等机制。异步I/O的技术就是使用AIO。
从I/O事件分派机制来看,使用select()是不合适的,因为它所支持的并发连接数有限(通常在1024个以内)。
如果考虑性能,poll()也是不合适的,尽管它可以支持的较高的TCP并发数,但是由于其采用
“轮询”机制,当并发数较高时,其运行效率相当低,并可能存在I/O事件分派不均,导致部分TCP
连接上的I/O出现“饥饿”现象。而如果使用epoll或AIO,则没有上述问题(早期Linux内核的AIO技术
实现是通过在内核中为每个 I/O请求创建一个线程来实现的,这种实现机制在高并发TCP连接的情形下
使用其实也有严重的性能问题。但在最新的Linux内核中,AIO的实现已经得到改进)。
综上所述,在开发支持高并发TCP连接的Linux应用程序时,应尽量使用epoll或AIO技术来实现并发的
TCP连接上的I/O控制,这将为提升程序对高并发TCP连接的支持提供有效的I/O保证。
内核参数sysctl.conf的优化
/etc/sysctl.conf 是用来控制linux网络的配置文件,对于依赖网络的程序(如web服务器和cache服务器)
非常重要,RHEL默认提供的最好调整。
推荐配置(把原/etc/sysctl.conf内容清掉,把下面内容复制进去):
net.ipv4.ip_local_port_range = 1024 65536
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_sack = 0
net.core.netdev_max_backlog = 30000
net.ipv4.tcp_no_metrics_save=1
net.core.somaxconn = 262144
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_max_orphans = 262144
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
这个配置参考于cache服务器varnish的推荐配置和SunOne 服务器系统优化的推荐配置。
varnish调优推荐配置的地址为:http://varnish.projects.linpro.no/wiki/Performance
不过varnish推荐的配置是有问题的,实际运行表明“net.ipv4.tcp_fin_timeout = 3”的配置
会导致页面经常打不开;并且当网友使用的是IE6浏览器时,访问网站一段时间后,所有网页都会
打不开,重启浏览器后正常。可能是国外的网速快吧,我们国情决定需要
调整“net.ipv4.tcp_fin_timeout = 10”,在10s的情况下,一切正常(实际运行结论)。
修改完毕后,执行:
/sbin/sysctl -p /etc/sysctl.conf
/sbin/sysctl -w net.ipv4.route.flush=1
命令生效。为了保险起见,也可以reboot系统。
调整文件数:
linux系统优化完网络必须调高系统允许打开的文件数才能支持大的并发,默认1024是远远不够的。
执行命令:
Shell代码
echo ulimit -HSn 65536 >> /etc/rc.local
echo ulimit -HSn 65536 >>/root/.bash_profile
ulimit -HSn 65536
❹ linux进程间通信 socket 共享内存 哪个快
进程间通讯进程间通信就是不同进程之间传播或交换信息,进程的用户空间是互相独立的,进程之间可以利用系统空间交换信息。 管道(pipe)管道是一种半双工的通信方式,数据只能单向流动。如果要进行双工通信,需要建立两个管道。 管道只能在具有亲缘关系的进程间使用,例如父子进程或兄弟进程。 有名管道(named pipe) 有名管道也是双半工的通信方式,但它允许无亲缘关系的进程间使用。 信号量(semophore) 信号量常用来作为一种锁机制来使用,它是一个记数器,用来控制多进程对共享资源的访问,防止多个进程同时访问一个共享资源。信号量主要用作为进程间或同一进程间不同线程之间的同步手段。 信号(sinal) 信号是一种比较复杂的通信方式,用于通知接收进程某些事件已经发生,要注意信号处理中调用的函数是否为信号安全。 消息队列(message queue) 消息队列是由消息的链表组成,存放在内核中并由消息队列标识符标识。 共享内存(shared memory) 共享内存就是映射一段被其他进程所访问的内存,这段共享内存由一个进程创建,可由多个进程访问。共享内存是最快的IPC方式,它是针对其他进程间通信方式的低运行效率而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。 套接字(socket) 套接字也是进程间通信的一种方式,与其他方式不同的是,它可以用在不同主机间的进程通信(也是它的主要用途)。 几种方式的缺点 管道: 速度慢,容量有限,只能用于亲缘关系进程间通信。 有名管道: 同管道,不过允许无亲缘关系进程间通信。 消息队列: 容量受系统限制,队列中会遗留数据,读时要考虑到这些未读完的数据。 信号量: 主要用于同步,无法传递复杂的数据信息。
❺ linux系统的进程间通信有哪几种方式
数据传输
一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间共享数据
多个进程想要操作共享数据,一个进程对共享数据通知事
一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。资源共享
多个进程之间共享同样的资源。为了作到这一点,需要内核提供锁和同步机制。进程控制
有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。早期UNIX进程间通信
基于System V进程间通信
基于Socket进程间通信
POSIX进程间通信。
管道(pipe),流管道(s_pipe)和有名管道(FIFO)
信号(signal)
消息队列
共享内存
信号量
套接字(socket)
管道:速度慢,容量有限,只有父子进程能通讯
FIFO:任何进程间都能通讯,但速度慢
消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题
信号量:不能传递复杂消息,只能用来同步
共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存
Linux 进程间通信(IPC)的发展
linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间通信方面的侧重点有所不同。
前者对Unix早期的进程间通信手段进行了系统的改进和扩充,形成了“system V IPC”,通信进程局限在单个计算机内;
后者则跳过了该限制,形成了基于套接口(socket)的进程间通信机制。
Linux则把两者继承了下来
UNIX进程间通信方式包括:管道、FIFO、信号。
System V进程间通信方式包括:System V消息队列、System V信号灯、System V共享内存
POSIX进程间通信包括:posix消息队列、posix信号灯、posix共享内存。
由于Unix版本的多样性,电子电气工程协会(IEEE)开发了一个独立的Unix标准,这个新的ANSI Unix标准被称为计算机环境的可移植性操作系统界面(PSOIX)。现有大部分Unix和流行版本都是遵循POSIX标准的,而Linux从一开始就遵循POSIX标准;
BSD并不是没有涉足单机内的进程间通信(socket本身就可以用于单机内的进程间通信)。事实上,很多Unix版本的单机IPC留有BSD的痕迹,如4.4BSD支持的匿名内存映射、4.3+BSD对可靠信号语义的实现等等。
linux使用的进程间通信方式
管道( pipe )
管道这种通讯方式有两种限制,一是半双工的通信,数据只能单向流动,二是只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
流管道s_pipe: 去除了第一种限制,可以双向传输.
管道可用于具有亲缘关系进程间的通信,命名管道:name_pipe克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
信号量( semophore )
信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数);
消息队列( message queue )
消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
信号 ( singal )
信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
主要作为进程间以及同一进程不同线程之间的同步手段。
共享内存( shared memory )
共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。
使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
套接字( socket )
套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信
更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。
进程间通信各种方式效率比较
类型
无连接
可靠
流控制
记录消息类型
优先级
普通PIPE N Y Y N
流PIPE N Y Y N
命名PIPE(FIFO) N Y Y N
消息队列 N Y Y Y
信号量 N Y Y Y
共享存储 N Y Y Y
UNIX流SOCKET N Y Y N
UNIX数据包SOCKET Y Y N N
注:无连接: 指无需调用某种形式的OPEN,就有发送消息的能力流控制:
如果系统资源短缺或者不能接收更多消息,则发送进程能进行流量控制
各种通信方式的比较和优缺点
如果用户传递的信息较少或是需要通过信号来触发某些行为.前文提到的软中断信号机制不失为一种简捷有效的进程间通信方式.
但若是进程间要求传递的信息量比较大或者进程间存在交换数据的要求,那就需要考虑别的通信方式了。
无名管道简单方便.但局限于单向通信的工作方式.并且只能在创建它的进程及其子孙进程之间实现管道的共享:
有名管道虽然可以提供给任意关系的进程使用.但是由于其长期存在于系统之中,使用不当容易出错.所以普通用户一般不建议使用。
消息缓冲可以不再局限于父子进程,而允许任意进程通过共享消息队列来实现进程间通信,并由系统调用函数来实现消息发送和接收之间的同步,从而使得用户在使用消息缓冲进行通信时不再需要考虑同步问题,使用方便,但是信息的复制需要额外消耗CPU的时间,不适宜于信息量大或操作频繁的场合。
共享内存针对消息缓冲的缺点改而利用内存缓冲区直接交换信息,无须复制,快捷、信息量大是其优点。
但是共享内存的通信方式是通过将共享的内存缓冲区直接附加到进程的虚拟地址空间中来实现的,因此,这些进程之间的读写操作的同步问题操作系统无法实现。必须由各进程利用其他同步工具解决。另外,由于内存实体存在于计算机系统中,所以只能由处于同一个计算机系统中的诸进程共享。不方便网络通信。
共享内存块提供了在任意数量的进程之间进行高效双向通信的机制。每个使用者都可以读取写入数据,但是所有程序之间必须达成并遵守一定的协议,以防止诸如在读取信息之前覆写内存空间等竞争状态的出现。
不幸的是,Linux无法严格保证提供对共享内存块的独占访问,甚至是在您通过使用IPC_PRIVATE创建新的共享内存块的时候也不能保证访问的独占性。 同时,多个使用共享内存块的进程之间必须协调使用同一个键值。
❻ linux在子进程中,client与server进行socket通信,客户端socket断开后不能与server连接,求高手指点
在不间断的建立连接过程中,每一次的连接断开会经过TCP状态的time_wait状态,这个状态的作用就是延迟一段时间,然后保证下一次连接的不会被当成上一次的连接。所以第二次的连接建立时如果没有经过一段时间第二次的连接会失败,报错会显示address in use这儿就是time_wait状态。你如果是在不同主机上进行不间断的连接肯定会出现上面的报错。