8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

我们先来看一段代码:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21#include

#include

#include

int ()

{

pid_t id;

id = fork();

if (id == 0)

{

printf("Hello from Child!, pid: %dn", getpid());

}

else

{

printf("Hello from Parent!, pid: %dn", getpid());

}

return 0;

}

执行结果如下:1

2

3

4~/codeDir/cCode/test # ./a.out

Hello from Parent!, pid: 2290

Hello from Child!, pid: 2291

~/codeDir/cCode/test #

我们看看进程状态:1

2

3

4~/codeDir # ps -a

PID TTY TIME CMD

2292 pts/2 00:00:00 ps

~/codeDir #

我们发现,进程直接退出了。

然后,我们再来看一段代码:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22#include

#include

#include

int ()

{

pid_t id;

id = fork();

if (id == 0)

{

printf("Hello from Child!, pid: %dn", getpid());

sleep(-1);

}

else

{

printf("Hello from Parent!, pid: %dn", getpid());

}

return 0;

}

我们让子进程无限阻塞住,然后父进程先退出。执行结果如下:1

2

3

4~/codeDir/cCode/test # ./a.out

Hello from Parent!, pid: 2314

Hello from Child!, pid: 2315

~/codeDir/cCode/test #

我们发现,终端不会卡住,而是直接退出了。说明,终端是否会卡住,是由父进程是否退出决定的。然后,我们看看进程状态:1

2

3

4

5~/codeDir # ps -a

PID TTY TIME CMD

2315 pts/4 00:00:00 a.out

2316 pts/2 00:00:00 ps

~/codeDir #

我们发现,此时子进程(PID是2315)还存在。因为进程2315的父进程2314不在了,所以进程2315会变成孤儿进程,此时,它的父进程会变成init进程。

此时,我们可以通过wait函数来等待子进程的结束:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23#include

#include

#include

int ()

{

pid_t id;

id = fork();

if (id == 0)

{

printf("Hello from Child!, pid: %dn", getpid());

sleep(-1);

}

else

{

wait(NULL);

printf("Hello from Parent!, pid: %dn", getpid());

}

return 0;

}

其中,wait可以等待子进程结束。代码执行结果如下:1

2~/codeDir/cCode/test # ./a.out

Hello from Child!, pid: 2327

我们发现,此时的终端没有直接退出。我们查看一下进程状态:1

2

3

4

5

6~/codeDir # ps -a

PID TTY TIME CMD

2326 pts/4 00:00:00 a.out

2327 pts/4 00:00:00 a.out

2329 pts/2 00:00:00 ps

~/codeDir #

我们发现,父进程和子进程都没挂掉。正是因为我们子进程一直没有退出,所以父进程阻塞在了wait这个地方。

我们再来看一段代码:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22#include

#include

#include

int ()

{

pid_t id;

id = fork();

if (id == 0)

{

printf("Hello from Child!, pid: %dn", getpid());

}

else

{

printf("Hello from Parent!, pid: %dn", getpid());

sleep(-1);

}

return 0;

}

目的是,子进程退出后,父进程一直阻塞住不退出。

执行结果如下:1

2

3~/codeDir/cCode/test # ./a.out

Hello from Parent!, pid: 2337

Hello from Child!, pid: 2338

因为父进程没有退出,所以终端会被卡住。此时,我们看看进程状态。1

2

3

4

5

6~/codeDir # ps -a

PID TTY TIME CMD

2337 pts/4 00:00:00 a.out

2338 pts/4 00:00:00 a.out

2339 pts/2 00:00:00 ps

~/codeDir #

我们发现,这里依然会看到子进程2338的信息,为什么呢?因为这个子进程目前是一个僵尸进程。我们发现这个进程旁边有一个标识defunct,代表这个进程执行完了它的任务,已经挂了,但是,这个进程的一些基本信息依然保存着。这个僵尸进程的信息依旧被内核保存在进程表里面。

我们现在用kill命令给僵尸进程发送信号看看:1

2

3

4

5

6

7~/codeDir # kill 2338

~/codeDir # ps -a

PID TTY TIME CMD

2337 pts/4 00:00:00 a.out

2338 pts/4 00:00:00 a.out

2342 pts/2 00:00:00 ps

~/codeDir #

我们发现,这个僵尸进程还是会被查找到?为什么呢?因为这个僵尸进程本来就是死的,当然kill会失效。那么,我们如何去避免这个问题呢?

可以用wait函数。wait函数除了可以等待子进程的结束,其实还可以获取到子进程的信息。这也是为什么一个子进程挂了之后,它的基本信息不会立马被内核清除的原因,因为,操作系统认为父进程会在某个时候要用到子进程的一些信息,例如子进程的退出状态。只有当父进程获取完子进程的信息之后,操作系统才会清理子进程残留的信息。而操作系统如何知道父进程读取过子进程的信息呢?那就是wait函数。实际上,wait函数可以传入一个获取子进程信息的结构体,只不过我们的代码没有去获取而已,说明此时我们是不关心子进程的状态的。

分析完之后,我们来看下一段代码:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24#include

#include

#include

int ()

{

pid_t id;

id = fork();

if (id == 0)

{

printf("Hello from Child!, pid: %dn", getpid());

sleep(1);

}

else

{

wait(NULL);

printf("Hello from Parent!, pid: %dn", getpid());

sleep(-1);

}

return 0;

}

这里,我们的父进程会去调用wait函数,等待子进程结束。等子进程执行完毕之后,父进程才回去执行。一旦父进程调用了wait函数,操作系统就知道父进程获取过子进程的信息,因此,操作系统就可以放心的去清理僵尸进程的残留信息了。

我们执行代码:1

2

3~/codeDir/cCode/test # ./a.out

Hello from Child!, pid: 2350

Hello from Parent!, pid: 2349

我们看看进程的状态:1

2

3

4

5~/codeDir # ps -a

PID TTY TIME CMD

2349 pts/4 00:00:00 a.out

2351 pts/2 00:00:00 ps

~/codeDir #

我们发现,子进程2350不再出现在进程状态列表里面了,说明子进程已经被清理完毕了。

linux c 函数专挑,Linux C wait函数相关推荐

  1. Linux宏定义实现类成员函数,全面解析Linux内核的同步与互斥机制

    http://blog.csdn.net/sailor_8318/archive/2008/06/30/2599357.aspx [摘 要]本文分析了内核的同步及互斥的几种机制:原子运算符(atomi ...

  2. Linux多任务编程之五:exit()和_exit()函数(转)

    来源:CSDN  作者:王文松   转自:Linux公社 ----------------------------------------------------------------------- ...

  3. linux系统发送信号的系统调用是,linux系统编程之信号:信号发送函数sigqueue和信号安装函数sigaction...

    信号发送函数sigqueue和信号安装函数sigaction sigaction函数用于改变进程接收到特定信号后的行为. sigqueue()是比较新的发送信号系统调用,主要是针对实时信号提出的(当然 ...

  4. Linux内核网络栈1.2.13-socket.c函数概述

    参考资料 <<linux内核网络栈源代码情景分析>> socket常用函数概述 根据socket提供的常用的库函数,socket,read,write等函数, 执行的过程 in ...

  5. Linux 多线程应用中编写安全的信号处理函数

    2019独角兽企业重金招聘Python工程师标准>>> Linux 多线程应用中编写安全的信号处理函数 在 开发多线程应用时,开发人员一般都会考虑线程安全,会使用 pthread_m ...

  6. 【Linux 内核 内存管理】RCU 机制 ④ ( RCU 模式下更新链表项 list_replace_rcu 函数 | 链表操作时使用 smp_wmb() 函数保证代码执行顺序 )

    文章目录 一.RCU 模式下更新链表项 list_replace_rcu 函数 二.链表操作时使用 smp_wmb() 函数保证代码执行顺序 一.RCU 模式下更新链表项 list_replace_r ...

  7. 【Android NDK 开发】NDK 交叉编译 ( NDK 函数库目录 | Linux 交叉编译环境搭建 | 指定头文件目录 | 指定函数库目录 | 编译 Android 命令行可执行文件 )

    文章目录 I . NDK platforms 目录下的 函数库 II . Ubuntu 配置 NDK 交叉编译环境 III . 同时指定编译的头文件和库文件 IV . 指定编译的头文件 V . 指定编 ...

  8. Linux之Shell脚本的条件判断和函数

    一.条件判断 1.if判断 (1)基本语法 if [ 条件判断式 ] then程序 fi 注意事项: 1.[ 条件判断式 ]中括号和条件判断式之间必须有空格 2.if后要有空格 (2)实操 输入一个数 ...

  9. 【Linux系统编程学习】C库IO函数与系统IO函数的关系

    此为黑马Linux课程笔记. 1. C标准IO函数工作流程 如图,以C库函数的fopen为例,其返回类型是FILE类型的指针,FILE类型包含很多内容,主要包含三个内容:文件描述符.文件读写指针的位置 ...

最新文章

  1. mysql日期函数 简书_ios怎样搭建php服务器
  2. 机器学习如何彻底改变游戏中的物理模拟
  3. burpsuite collaborato模块简介 dns log、http_https log、smtp_smtps log
  4. 移动端布局的几种方式
  5. 二叉树的建立与遍历(先中后层序)
  6. 第四范式发布Sage AIOS 2.0及智能应用市场Sage App Store
  7. 阿里技术高P访谈之张俭恭:情义是阿里与外企的最大不同
  8. Adobe illustrator 论文图形编辑和排版 - 连载 1
  9. 抖音、微信读书都被诉侵权,法院这样判,但两者回应却不一样?
  10. Ramfs、rootfs 和initramfs
  11. 【Flutter】微信项目实战【04】发现界面搭建
  12. 3.SPSS Modeler数据基本分析笔记
  13. 随便说说,关于电吉他这个爱好
  14. 用matlab实现“太阳-地球-月亮运行示意图”动画
  15. 什么是企业移动化?以及企业移动化的4大特征
  16. WPF中应用toolkit Chart控件安装
  17. python代码画樱花-如何用Python代码实现樱花树效果
  18. 君正平台JZ4775芯片参数详细说明,大家可以看看
  19. METATRADER 5 中的订单、持仓和成交
  20. Jedis 读写效率测试 hgetAll hmset

热门文章

  1. 计图(Jittor) 1.1版本:新增骨干网络、JIT功能升级、支持多卡训练
  2. Linux下Flash-LED的处理
  3. 2021年大数据Spark(七):应用架构基本了解
  4. MySQL新建数据库+用Navicat查看MySQL的方法
  5. CountDownTimer 实现验证码倒计时
  6. Kotlin implements 的实现
  7. JSOI2010 BZOJ1826 缓存交换
  8. Cannot find snapshot in models/VGGNet/VOC0712/SSD_300x300
  9. 0x58 数据结构优化DP
  10. 虚拟机VMware下CentOS6.6安装教程图文详解