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. Python装饰器Decorators

    def hi(name="yasoob"): return "hi " + name print(hi()) # 我们甚至可以将一个函数赋值给一个变量,比如 g ...

  2. Training loop Run Builder

    以下内容来自deeplizard pyorch_P31  

  3. 2021.03.13【NOIP提高A&B组】模拟 总结

    T1 题目大意:从原点开始循环执行命令,问最后的位置 好吧这就是一道幼儿园的周期问题,模拟即可 #include<bits/stdc++.h> using namespace std; c ...

  4. .Net CLR GC动态获取函数头地址,C++的骚操作(慎入)

    前言: 太懒了,从没有在这里正儿八经的写过文章.看到一些人的高产,真是惭愧.决定稍微变得不那么懒.如有疏漏,请指正. .net的GC都谈的很多了,本篇主要是剑走偏锋,聊聊一些个人认为较为核心的细节方面 ...

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

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

  6. RPA应用场景-海关报关

    场景概述海关报关 所涉系统名称海关页面,业务核心系统 人工操作(时间/次) 10 分钟 所涉人工数量 3 操作频率实时 场景流程 1.每日接收报关申请邮件: 2.根据邮件信息进入业务核心系统查询相关数 ...

  7. (原创)【MAUI】一步一步实现“悬浮操作按钮”(FAB,Floating Action Button)

    一.前言 MAUI,跨平台的 GUI 框架,基本介绍本文不再赘述. 话不多说,既然可以跨平台,那么我们就来实现一个在移动端很常用的控件:悬浮操作按钮(FAB,Floating Action Butto ...

  8. NC15979 小q的数列

    NC15979 小q的数列 题目 题目描述 小q最近迷上了各种好玩的数列,这天,他发现了一个有趣的数列,其递推公式如下: \[f[i] = \left\{ \begin{array}{l} 0 ,&a ...

  9. AI2(App Inventor 2) 离线版

    介绍 我们的目标:搭建一个本地多用户的App Inventor 2 服务器目的:课堂教学,社团活动,兴趣学习优势:管理权限(用户管理,账号切换,资源打包),网络链接速度快,拥有配套服务.注意:每次退出 ...

  10. 08 MySQL_SQL_DQL_select数据查询条件判断

    导入*.sql数据到数据库 windows系统 ​ source d:/tables.sql; Linux系统 source /home/soft/桌面/tables.sql; 导入完成后 测试查询 ...