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. 用Arduino玩GM65二维码扫描模块

    目录 用Arduino玩GM65二维码扫描模块 用Arduino玩GM65二维码扫描模块 最近在做Capstone,内容是我们之前实验室参加过的工程训练的物流搬运小车,所以现在来复盘一下我使用Ardu ...

  2. 字节开源RPC框架Kitex的日志库klog源码解读

    前言 这篇文章将着重于分析字节跳动开源的RPC框架Kitex的日志库klog的源码,通过对比Go原生日志库log的实现,探究其作出的改进. 为了平滑学习曲线,我写下了这篇分析Go原生log库的文章,希 ...

  3. 深度学习与CV教程(13) | 目标检测 (SSD,YOLO系列)

    作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/37 本文地址:http://www.showmeai.tech/article-det ...

  4. 掘地三尺搞定 Redis 与 MySQL 数据一致性问题

    Redis 拥有高性能的数据读写功能,被我们广泛用在缓存场景,一是能提高业务系统的性能,二是为数据库抵挡了高并发的流量请求,点我 -> 解密 Redis 为什么这么快的秘密. 把 Redis 作 ...

  5. MySQL 8.0 新特性梳理汇总

    一 历史版本发布回顾 从上图可以看出,基本遵循 5+3+3 模式 5---GA发布后,5年 就停止通用常规的更新了(功能不再更新了): 3---企业版的,+3年功能不再更新了: 3 ---完全停止更新 ...

  6. numpy学习笔记 01

    NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库. NumPy 是一个运行速度非常快的数学库 ...

  7. python素描照片

    #!/usr/bin/python # -*- coding: utf-8 -*- from PIL import Image import numpy as np a = np.asarray(Im ...

  8. 文本处理工具-vim编辑器的常见用法

    文本编辑工具分类: (1)全屏编辑器: nano(字符编辑器).vi.vim (2)行编辑器: sed:可以逐行改文件 vi编辑器 全名:Visual editor,linux系统自带的文本编辑工具 ...

  9. PotPlayer播放百度云盘视频

    需要的工具 PotPlayer.油猴tampermonkey.坚果(这个不用下载,有个账号就行) 下载地址:百度网盘 步骤 安装油猴tampermonkey 拖拽Tampermonkey_4.14.c ...

  10. web文本划线的极简实现

    开篇 文本划线是目前逐渐流行的一个功能,不管你是小说阅读网站,还是卖教程的的网站,一般都会有记笔记或者评论的功能,传统的做法都是在文章底部加一个评论区,优点是简单,统一,缺点是不方便对文章的某一段或一 ...