关于Redis在windows上运行及fork函数问题
Redis在将数据库进行持久化操作时,需要fork一个进程,但是windows并不支持fork,导致在持久化操作期间,Redis必须阻塞所有的客户端直至持久化操作完成。微软的一些工程师花费时间在解决在windows环境下Redis无法进行后台保存,并决定使用线程代替fork产生的子进程来对硬盘执行写操作,但这给分支只提供了源码并没有提供预编译二进制文件,并且微软不保证它能否用于生产环境。
上面这段是我摘抄于黄健宏老师翻译的《Redis实战》这本书的。
下面我解释一下fork函数的一些问题
- fork函数
fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程。
下面的侧重点在于fork与递归的区分。
创建fork_test1.c
我们可以touch fork_test1.c,
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
int main(int argc, char **argv) {
pid_t pid = fork();
if (pid==0) {
printf("我是父进程,pid是: %d\n",getpid());
exit(0);
} else if (pid > 0) {
printf("我是子进程,pid是: %d\n",getpid());
} else {
printf("Error while forking\n");
exit(EXIT_FAILURE);
}
return 0;
}
使用cc fork_test.c进行编译。
执行可执行文件a.out
./a.out
我是子进程,pid是: 1492
我是父进程,pid是: 1493
为什么没有死递归
观察执行结果会发现的子进程的返回值是0,至于为什么是0,暂不讨论。
我好奇的是程序为什么没有进行死递归,因为我认为程序会复制一份重新运行。
经过一番查阅后发现,因为,fork是复制父进程的数据段,堆,栈等,因此,父进程与子进程执行程序位置也是相同的,函数fork完之后,父进程与子进程同时执行到到了第一个if语句,因此子进程并不会重新执行fork()函数,因此没有递归。
验证一下
我们可以touch fork_test2.c,
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
int main(int argc, char **argv) {
printf("abcd");
pid_t pid = fork();
if (pid==0) {
printf("我是父进程,pid是: %d\n",getpid());
exit(0);
} else if (pid > 0) {
printf("我是子进程,pid是: %d\n",getpid());
} else {
printf("Error while forking\n");
exit(EXIT_FAILURE);
}
return 0;
}
编译
cc fork_test2.c
执行
./a.out
你会发现程序没有死递归。
上面难道是错的
但是观察结果你会发现为什么"abcd"输出了两次,不是两个进程都执行到了第一个if语句吗?为什么子进程也会输出。
上面讲的并没有错,你应该注意到,fork()的复制就包括输出缓冲区。
而程序并不会立即把输出的数据显示到屏幕上,而是先存储在输出缓冲区中,当满足一定条件时才显示出来。
输出缓冲区类型
缓冲区的类型:
缓冲区 分为三种类型:全缓冲、行缓冲和不带缓冲。
1、全缓冲
在这种情况下,当填满标准I/O缓存后才进行行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。
2、行缓冲
在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是键盘输入数据。
3、不带缓冲
也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。
所以,因为我们的fork_test2.c没有触发任何刷新缓冲区的操作,因此复制的时候子进程的缓冲区中也会有"abcd",所以就会输出两次。
如何触发缓冲区刷新
那么我们就触发缓冲区刷新的操作,如何触发呢?
1、遇到\n
2、程序结束
3、遇到输入语句
4、当缓冲区满时
5、fflush(stdout) 手动刷新
我们尝试用第一种方法修改代码,
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
int main(int argc, char **argv) {
printf("abcd\n");
pid_t pid = fork();
if (pid==0) {
printf("我是父进程,pid是: %d\n",getpid());
exit(0);
} else if (pid > 0) {
printf("我是子进程,pid是: %d\n",getpid());
} else {
printf("Error while forking\n");
exit(EXIT_FAILURE);
}
return 0;
}
拨云见日
然后重新编译运行,你会发现"abcd"只会被输出一次,子进程复制的输出缓冲区为空。到此解释了fork·与递归的一些问题。
如果有什么问题大家可以在下面留言。
关于Redis在windows上运行及fork函数问题的更多相关文章
- redis 在windows上运行
参考自:https://github.com/ServiceStack/redis-windows 1.用vagrant 运行redis的最后版本 1.1在windows上安装vagrant http ...
- 大数据高性能数据库Redis在Windows上的使用教程
Redis学习笔记----Redis在windows上的安装配置和使用 Redis简介 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括s ...
- 使 IIS 6.0 可以在 64 位 Windows 上运行 32 位应用程序 试图加载格式不正确的程序。
原文 使 IIS 6.0 可以在 64 位 Windows 上运行 32 位应用程序 试图加载格式不正确的程序. win7 64位操作系统上边运行IIS网站应用的时候,提示错误"试图加载格式 ...
- 如何实现在Windows上运行Linux程序,附示例代码
微软在去年发布了Bash On Windows, 这项技术允许在Windows上运行Linux程序, 我相信已经有很多文章解释过Bash On Windows的原理, 而今天的这篇文章将会讲解如何自己 ...
- 在Windows上运行Linux
在Windows上运行Linux 之前了解过一些适用于linux的Windows子系统,最近又听人提起,于是在自己的Windows 10专业版上安装了一个Ubuntu.运行起来还真方便,以后在wind ...
- Docker在Linux/Windows上运行NetCore文章系列
Windows系列 因为Window很简单,VS提供界面化配置,所以只写了一篇文章 Docker在Windows上运行NetCore系列(一)使用命令控制台运行.NetCore控制台应用 Linux( ...
- Docker在Windows上运行NetCore系列(一)使用命令控制台运行.NetCore控制台应用
系列文章:https://www.cnblogs.com/alunchen/p/10121379.html 本篇文章操作系统信息 Windows:Window 10 Visual Studio:201 ...
- 如何使用Cygwin在Windows上运行OpenSSH SSHD服务器
记录几款非常有趣, 但不怎么耳熟的软件: Cygwin 是可以安装 OpenSSH server 和 client 的, Mosh 也可以, 这对于 Linux 用户而言就非常方便了. 如何使用Cyg ...
- 电脑出现“损坏的图像”窗口提示dll没有被指定在Windows上运行如何解决
电脑中出现了无法运行应用程序的情况,弹出一个“***.exe - 损坏的图像”的窗口,上面提示“***.dll没有被指定在Windows上运行……”,如果我们遇到这样的问题,应该要如何解决呢? 1.我 ...
随机推荐
- 【摸鱼神器】UI库秒变LowCode工具——列表篇(一)设计与实现
内容摘要: 需求分析 定义 interface 定义 json 文件 定义列表控件的 props 基于 el-table 封装,实现依赖 json 渲染 实现内置功能:选择行(单选.多选),格式化.锁 ...
- React项目实现导出PDF的功能
在做web项目中,有时候会遇到pdf导出的需求,现根据之前在公司的React项目中遇到的导出PDF需求,整理一个demo出来. 导出PDF需要用到两个依赖包:html2canvas.jspdf 1.安 ...
- 架构师必备:HBase行键设计与应用
首先要回答一个问题,为何要使用HBase? 随着业务不断发展.数据量不断增大,MySQL数据库存在这些问题: MySQL支持的数据量为TB级,不能一直保留历史数据.而HBase支持的数据量为PB级,适 ...
- php 二维数组转换一维数组
$result = array_reduce($res, function ($result, $value) { return array_merge($result, array_values($ ...
- CYaRon!语
P3695 CYaRon!语 开始之前 上次水了些小模拟之后感觉不能再颓废了,于是就来大模拟. 然后这个题花了我一个多星期 还是最差解 不过,为了纪念我的第 20 道紫题,纪念我这一周的努力,我还是想 ...
- 6000字Locust入门详解
目录 一.Locust 性能测试 (一). 性能测试工具 主流性能测试工具对比 认识Locust (二) locust 基本用法 1.安装locust 2.编写用例 3. 启动测试 GUI 模式启动 ...
- Pytorch实现波阻抗反演
Pytorch实现波阻抗反演 1 引言 地震波阻抗反演是在勘探与开发期间进行储层预测的一项关键技术.地震波阻抗反演可消除子波影响,仅留下反射系数,再通过反射系数计算出能表征地层物性变化的物理参数.常用 ...
- 【python基础】第10回 周总结
路径 可以简单的理解为路径就是某个事物所在的具体位置(坐标) 1.相对路径:必须有一个参考系,就是相对于自己的目标文件的位置. 2.绝对路劲:不需要有参考系,是指文件在硬盘上真正存在的路径. 计算机五 ...
- 关于Java中的构造方法
关于构造方法: 1.构造方法又叫构造函数/构造器. 2.构造方法语法结构中"返回值类型"不需要指定,也不能写void,如若写void,则变成普通方法. 3.构造方法有返回值,和当前 ...
- 异构图神经网络笔记-Heterogeneous Graph Neural Network(KDD19)
自己讲论文做的异构图神经网络的ppt.再转变成博客有点麻烦,所以做成图片笔记. 论文链接:https://arxiv.org/abs/1903.07293