首页 > 数据库 >关于Redis在windows上运行及fork函数问题

关于Redis在windows上运行及fork函数问题

时间:2022-08-23 09:12:28浏览次数:71  
标签:fork windows Redis pid 缓冲区 printf 进程 include

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·与递归的一些问题。

如果有什么问题大家可以在下面留言。

标签:fork,windows,Redis,pid,缓冲区,printf,进程,include
From: https://www.cnblogs.com/TanAn/p/16614933.html

相关文章

  • 数据库 - db和redis数据一致性问题
    数据库-db和redis数据一致性问题直接说解决办法:查询数据操作:查询缓存,如果命中,直接返回;如果没有命中,查询数据库,再写入缓存更新数据操作:直接更新db数据库然后......
  • windows 进程占用的万能解决方法
    问题错误:操作无法完成,因为文件夹已在另一个程序中打开(theactioncan'tbecompletedbecausethefolderorafileinitisopeninanotherprogram) 解决看到......
  • Redis基础练习题-错题集(一)
    (1)下面关于Redis中set数据类型与list数据类型的比较,正确的说法是()选项A. set中的数据具有唯一性,list中的数据不具有唯一性B. set中的数据有序,list中的数据无序......
  • Redis中set和list的区别有哪些
    list和set的区别:1、List和Set都是接口继承于Collection接口。2、最大的不同就是List是可以重复的。而Set是不能重复的。(注意:元素虽然无放入顺序,但是元素在set中的位置是......
  • Windows10/11 三步安装wsl2 Ubuntu20.04(任意盘)
    如果你是Windows用户的话,觉得使用Linux很不方便,那么这篇文章可以给你提供一个还算舒适的Windows10下Linux开发的环境,并且不需要多高的配置,也可以很顺畅的使用。(我的笔记本......
  • elasticsearch安装(Windows)遇到的问题
    1、运行:/bin/elasticsearch.bat注意:9300为ElasticSearch集群间组件的通信端口,9200为浏览器访问的http协议RESTful端口;输入地址http://localhost:9200结果:访问失败!尚......
  • ssh连接windows10拒绝连接-SSH入站-windows开启SSH
    第一步:ssh使用的22端口,首先确认windows10的22端口是否开启。--开启步骤1.控制面板-->WindwsDefender防火墙-->高级设置-->入站规则-->新建规则2.选择端口-->下一步3......
  • FTP服务搭建-Windows Server 2008搭建FTP服务
         在与银行进行存管测试的时候,需要搭建FTP服务来进行文件交互,搭建步骤如下: 一、概述搭建FTP服务主要有以下几个步骤:1.安装FTP服务2.创建FTP专用账号3.......
  • 如何查看redis使用那个配置文件启动
      [root@cdc-henan-cdhworker02redis]#/usr/local/redis/bin/redis-cli-h192.168.1.50-atest123-p6379Warning:Usingapasswordwith'-a'or'-u'option......
  • winform开发windows服务过程简要回顾
    总结下,winform开发windows服务全过程 ;windows服务的代码中,不能有MessageBox.Show()等winform的控件引用。可以使用写文本日志的方法调试;1、添加服务引用,输入webservice......