php利用socket_pair进程通信,nginx 进程间通信-socketpair
在nginx中,master进程与worker进程之间使用了一种全双工通信方式--socketpair。socketpair 函数成功执行后会创建一对已经建立连接的socket对,两个相互通信的进程分别使用其中一个socket进行读写操作,就能够实现两进程间的通信。
查看nginx源码,可以看到,下面的函数创建了socketpairngx_pid_t
ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
char *name, ngx_int_t respawn)
{
u_long on;
ngx_pid_t pid;
ngx_int_t s;
/. ......省略...... ./
if (respawn != NGX_PROCESS_DETACHED) {
/* Solaris 9 still has no AF_LOCAL */
//创建socketpair
if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1)
{
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
"socketpair() failed while spawning \"%s\"", name);
return NGX_INVALID_PID;
}
//非阻塞
if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) {
ngx_close_channel(ngx_processes[s].channel, cycle->log);
return NGX_INVALID_PID;
}
//非阻塞
if (ngx_nonblocking(ngx_processes[s].channel[1]) == -1) {
ngx_close_channel(ngx_processes[s].channel, cycle->log);
return NGX_INVALID_PID;
}
//异步
on = 1;
if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) {
ngx_close_channel(ngx_processes[s].channel, cycle->log);
return NGX_INVALID_PID;
}
//设置将要在文件描述词fd上接收SIGIO 或 SIGURG事件信号的进程或进程组标识 。
if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) {
ngx_close_channel(ngx_processes[s].channel, cycle->log);
return NGX_INVALID_PID;
}
//设置close_on_exec,当通过exec函数族创建了新进程后,原进程的该socket会被关闭
if (fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC) == -1) {
ngx_close_channel(ngx_processes[s].channel, cycle->log);
return NGX_INVALID_PID;
}
//设置close_on_exec,当通过exec函数族创建了新进程后,原进程的该socket会被关闭
if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) {
ngx_close_channel(ngx_processes[s].channel, cycle->log);
return NGX_INVALID_PID;
}
ngx_channel = ngx_processes[s].channel[1];
} else {
ngx_processes[s].channel[0] = -1;
ngx_processes[s].channel[1] = -1;
}
ngx_process_slot = s;
pid = fork();
switch (pid) {
case -1:
ngx_close_channel(ngx_processes[s].channel, cycle->log);
return NGX_INVALID_PID;
case 0:
//fork成功,子进程创建,同时相关socket描述符也会被复制一份
ngx_pid = ngx_getpid();
proc(cycle, data);
break;
default:
break;
}
/. ......省略...... ./
return pid;
}
fork成功后,原进程的descriptor也会被复制一份,如果在fork的进程中该描述符不再使用,需要我们及时关闭。
如果我们使用的是 fork->exec函数族 的形式创建新进程的话,我们可以采用更好的办法来确保原有的descriptor被正常关闭,避免资源的泄漏。也就是上边代码中对socket调用fcntl(FD_CLOEXEC)函数,设置该socket的属性:当exec函数族被调用后,该socket会被自动关闭。使用这种在socket创建后立即设置FD_CLOEXEC属性的办法,避免了我们在exec创建进程前手动关闭相关socket的操作,尤其是当有大量的descriptor被创建、管理的时候非常实用。
很多时候我们是使用下边的方法进行操作的:#include #include #include #include int main()
{
pid_t pid;
int fds[2];
int valRead, valWrite;
if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, fds))
{
return 0;
}
pid = fork();
if (0 == pid)
{
pid = getpid();
printf("[%d]-child process start", pid);
close(fds[0]);
//read write on fds[1]
write(fds[1], &valWrite, sizeof(valWrite));
read(fds[1], &valRead, sizeof(valRead));
}
else if (0 < pid)
{
pid = getpid();
printf("[%d]-parent process continue", pid);
close(fds[1]);
//read write on fds[0]
read(fds[0], &valRead, sizeof(valRead));
write(fds[0], &valWrite, sizeof(valWrite));
}
else
{
printf("%s", "fork failed");
}
return 0;
}
可以看到,fork前,当前进程创建了一对socket,也就是socketpair。对于这对socket,可以看作一个是服务器端fds[0],另一个是客户端fds[1],通过fds[0]与fds[1]之间建立的链接,我们可以完成全双工通信。
fork执行后,创建了子进程。在子进程中,之前父进程创建的socketpair自然也会被复制一份为fds',存在于子进程中。父进程继续执行。这个时候,在父进程和子进程中会存在相同socketpair。
试想,我们在主进程中向fds[0]中写入数据,在子进程中的fds'[1]上就会读取到该数据,这样就实现了父进程与子进程间的通信。当然,在主进程fds[1]上写数据,在子进程fds'[0]上也会读到写入的数据。我们实际使用中,只需要保留一对socket用来通信就可以了,另外两个socket就可以分别在父进程和子进程中关闭不用了。
当然了,如果我们能够把fds中的一个socket通过某种方式传递给另一个进程,那么也可以实现socketpair进程间通信了。
以上就介绍了nginx 进程间通信-socketpair,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。
本文原创发布php中文网,转载请注明出处,感谢您的尊重!
php利用socket_pair进程通信,nginx 进程间通信-socketpair相关推荐
- php利用socket_pair进程通信,Linux上实现双向进程间通信管道(socketpair)
管道pipe是半双工的,pipe两次才能实现全双工,使得代码复杂.socketpair直接就可以实现全双工 socketpair对两个文件描述符中的任何一个都可读和可写,而pipe是一个读,一个写 L ...
- python进程socket通信_python3 进程间通信之socket.socketpair()
python3 进程间通信之socket.socketpair() socket.socketpair()是什么鬼东西? socket.socketpair()函数仅返回两个已经连接的套接字对象,参数 ...
- NGINX 进程通信机制
nginx的进程通信分为三种类别:linux 系统与nginx 通信, master 进程与worker进程通信, worker进程间通信. master进程管理worker进程,本文将追溯nginx ...
- 利用Messenger跨进程通信
在进行跨进程通信的时候,可能很多开发者一开始想到的就是AIDL.AIDL,中文名称是android接口描述语言,是android系统中用于进行跨进程通信必须了解的.至于如何生成远程对象进行AIDL通信 ...
- 利用FindWindow和SendMessage进程通信
利用FindWindow和SendMessage,特此记下. 首先说FindWindow. FindWindow返回与指定字符创相匹配的窗口类名或窗口名的最顶层窗口的窗口句柄.函数原型为: ...
- Unix domain socket 简介(进程间通信,进程通信)
Unix domain socket 又叫 IPC(inter-process communication 进程间通信) socket,用于实现同一主机上的进程间通信.socket 原本是为网络通讯设 ...
- c语言程序实现进程的管道通信,C 进程间通信--命名管道通信代码实现及其原理图示...
在将这个题目之前大家需要了解几个概念: 进程: 我们可以先看进程的定义:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础: ...
- 【免杀前置课——Windows编程】十、进程间通信(COPY_DATA通信,邮槽通信)、实现两进程通信(附代码)
进程间通信 进程间通信 1.COPY_DATA方式 2.邮槽的方式 实现两进程通信 进程接收端 进程发送端 错误调试小技巧 进程间通信 每个进程都有自己独立的4G内存空间,彼此是不能直接互相访问的.如 ...
- Android IPC 进程进程间通信或跨进程通信
Android IPC 机制 老话长谈,趁现在有时间对IPC做一个具体的总结. IPC是Inter-Process Communication的缩写,含义就是进程间通信或者跨进程通信,是指两个进程之间 ...
最新文章
- P5667 拉格朗日插值2(拉格朗日插值,NTT, 倒推求逆元)
- pytorch cpu gpu性能对比
- Gradient Boosting, Decision Trees and XGBoost with CUDA ——GPU加速5-6倍
- 【Android 逆向】修改运行中的 Android 进程的内存数据 ( 使用 IDA 分析要修改的内存特征 | 根据内存特征搜索修改点 | 修改进程内存 )
- jquery遍历集合数组标签
- java递归遍历目录文件
- Centos 7 密码重置
- 近现代科学三大发现:证实佛法真实不虚
- Matlab:Matlab编程语言的简介、安装、学习路线(几十项代码编程案例分析)之详细攻略
- blob jdbc mysql_JDBC中级篇(MYSQL)——处理文件(BLOB)
- FusionChartsFree用法简介
- 高一计算机会考英语作文,高一考试英语作文常考题目及范文
- 弄清楚这个三角关系,工作效率提高50%
- 网页色彩大攻略(蓝色系)
- 【科学文献计量】networkx绘制网络图的基本属性,图形读写以及无向/有向图形绘制详解
- HashMap底层扩容机制是2倍的原理
- 2.机器学习基础(一)
- Oracle 数据仓库 ETL 技术之多表插入语句
- 不要乱用position:fixed
- Python Journey - Day2 - 基本数据类型
热门文章
- cocoscreator 中 spine局部换皮
- 浅析AI人脸识别/车辆识别智能分析网关的深度学习算法及应用场景
- 兰州交通大学博文学院计算机协会生日,兰州交通大学博文学院微博协会首届wps办公软件大赛(孙威虎).doc...
- Chrome 96 版本无法携带cookie问题的终极解决方案+源码分享
- WMS仓储管理系统如何帮助纺织企业实现仓库智能管理
- stm32/gd32爱玛电动车控制器资料 电动车控制器原理图、PCB和程序
- LaTex入门教程-中文版-免费下载.pdf
- python手机按键脚本教程-Appium+Python-模拟手机按键操作
- 北京益序医疗完成数千万元新一轮融资,澜峰医疗独投
- php中文乱码问号,解决PHP中文乱码问题