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函数问题的更多相关文章

  1. redis 在windows上运行

    参考自:https://github.com/ServiceStack/redis-windows 1.用vagrant 运行redis的最后版本 1.1在windows上安装vagrant http ...

  2. 大数据高性能数据库Redis在Windows上的使用教程

    Redis学习笔记----Redis在windows上的安装配置和使用 Redis简介 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括s ...

  3. 使 IIS 6.0 可以在 64 位 Windows 上运行 32 位应用程序 试图加载格式不正确的程序。

    原文 使 IIS 6.0 可以在 64 位 Windows 上运行 32 位应用程序 试图加载格式不正确的程序. win7 64位操作系统上边运行IIS网站应用的时候,提示错误"试图加载格式 ...

  4. 如何实现在Windows上运行Linux程序,附示例代码

    微软在去年发布了Bash On Windows, 这项技术允许在Windows上运行Linux程序, 我相信已经有很多文章解释过Bash On Windows的原理, 而今天的这篇文章将会讲解如何自己 ...

  5. 在Windows上运行Linux

    在Windows上运行Linux 之前了解过一些适用于linux的Windows子系统,最近又听人提起,于是在自己的Windows 10专业版上安装了一个Ubuntu.运行起来还真方便,以后在wind ...

  6. Docker在Linux/Windows上运行NetCore文章系列

    Windows系列 因为Window很简单,VS提供界面化配置,所以只写了一篇文章 Docker在Windows上运行NetCore系列(一)使用命令控制台运行.NetCore控制台应用 Linux( ...

  7. Docker在Windows上运行NetCore系列(一)使用命令控制台运行.NetCore控制台应用

    系列文章:https://www.cnblogs.com/alunchen/p/10121379.html 本篇文章操作系统信息 Windows:Window 10 Visual Studio:201 ...

  8. 如何使用Cygwin在Windows上运行OpenSSH SSHD服务器

    记录几款非常有趣, 但不怎么耳熟的软件: Cygwin 是可以安装 OpenSSH server 和 client 的, Mosh 也可以, 这对于 Linux 用户而言就非常方便了. 如何使用Cyg ...

  9. 电脑出现“损坏的图像”窗口提示dll没有被指定在Windows上运行如何解决

    电脑中出现了无法运行应用程序的情况,弹出一个“***.exe - 损坏的图像”的窗口,上面提示“***.dll没有被指定在Windows上运行……”,如果我们遇到这样的问题,应该要如何解决呢? 1.我 ...

随机推荐

  1. 【摸鱼神器】UI库秒变LowCode工具——列表篇(一)设计与实现

    内容摘要: 需求分析 定义 interface 定义 json 文件 定义列表控件的 props 基于 el-table 封装,实现依赖 json 渲染 实现内置功能:选择行(单选.多选),格式化.锁 ...

  2. React项目实现导出PDF的功能

    在做web项目中,有时候会遇到pdf导出的需求,现根据之前在公司的React项目中遇到的导出PDF需求,整理一个demo出来. 导出PDF需要用到两个依赖包:html2canvas.jspdf 1.安 ...

  3. 架构师必备:HBase行键设计与应用

    首先要回答一个问题,为何要使用HBase? 随着业务不断发展.数据量不断增大,MySQL数据库存在这些问题: MySQL支持的数据量为TB级,不能一直保留历史数据.而HBase支持的数据量为PB级,适 ...

  4. php 二维数组转换一维数组

    $result = array_reduce($res, function ($result, $value) { return array_merge($result, array_values($ ...

  5. CYaRon!语

    P3695 CYaRon!语 开始之前 上次水了些小模拟之后感觉不能再颓废了,于是就来大模拟. 然后这个题花了我一个多星期 还是最差解 不过,为了纪念我的第 20 道紫题,纪念我这一周的努力,我还是想 ...

  6. 6000字Locust入门详解

    目录 一.Locust 性能测试 (一). 性能测试工具 主流性能测试工具对比 认识Locust (二) locust 基本用法 1.安装locust 2.编写用例 3. 启动测试 GUI 模式启动 ...

  7. Pytorch实现波阻抗反演

    Pytorch实现波阻抗反演 1 引言 地震波阻抗反演是在勘探与开发期间进行储层预测的一项关键技术.地震波阻抗反演可消除子波影响,仅留下反射系数,再通过反射系数计算出能表征地层物性变化的物理参数.常用 ...

  8. 【python基础】第10回 周总结

    路径 可以简单的理解为路径就是某个事物所在的具体位置(坐标) 1.相对路径:必须有一个参考系,就是相对于自己的目标文件的位置. 2.绝对路劲:不需要有参考系,是指文件在硬盘上真正存在的路径. 计算机五 ...

  9. 关于Java中的构造方法

    关于构造方法: 1.构造方法又叫构造函数/构造器. 2.构造方法语法结构中"返回值类型"不需要指定,也不能写void,如若写void,则变成普通方法. 3.构造方法有返回值,和当前 ...

  10. 异构图神经网络笔记-Heterogeneous Graph Neural Network(KDD19)

    自己讲论文做的异构图神经网络的ppt.再转变成博客有点麻烦,所以做成图片笔记. 论文链接:https://arxiv.org/abs/1903.07293