Linux下面,创建进程是一件十分有意思的事情。我们都知道,进程是操作系统下面享有资源的基本单位。那么,在linux下面应该怎么创建进程呢?其实非常简单,一个fork函数就可以搞定了。但是,我们需要清楚的是子进程与父进程之间除了代码是共享的之外,堆栈数据和全局数据均是独立的,主要是学习标准的H文件的包含。

 linux下的C语言开发(创建进程)

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #include <errno.h>
  6. #include <sys/types.h>
  7. #include <sys/wait.h>
  8. int main()
  9. {
  10. pid_t pid;
  11. if(-1 == (pid = fork()))
  12. {
  13. printf("Error happened in fork function!\n");
  14. return 0;
  15. }
  16. if(0 == pid)
  17. {
  18. printf("This is child process: %d\n", getpid());
  19. }
  20. else
  21. {
  22. printf("This is parent process: %d\n", getpid());
  23. }
  24. return 0;
  25. }

==================================================================================

linux下的C语言开发(多线程编程)

多线程和多进程还是有很多区别的。其中之一就是,多进程是Linux内核本身所支持的,而多线程则需要相应的动态库进行支持。对于进程而言,数据之间都是相互隔离的,而多线程则不同,不同的线程除了堆栈空间之外所有的数据都是共享的。说了这么多,我们还是自己编写一个多线程程序看看结果究竟是怎么样的。

  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. void func_1(void* args)
  6. {
  7. while(1){
  8. sleep(1);
  9. printf("this is func_1!\n");
  10. }
  11. }
  12. void func_2(void* args)
  13. {
  14. while(1){
  15. sleep(2);
  16. printf("this is func_2!\n");
  17. }
  18. }
  19. int main()
  20. {
  21. pthread_t pid1, pid2;
  22. if(pthread_create(&pid1, NULL, func_1, NULL))
  23. {
  24. return -1;
  25. }
  26. if(pthread_create(&pid2, NULL, func_2, NULL))
  27. {
  28. return -1;
  29. }
  30. while(1){
  31. sleep(3);
  32. }
  33. return 0;
  34. }

和我们以前编写的程序有所不同,多线程代码需要这样编译,输入gcc thread.c -o thread -lpthread,编译之后你就可以看到thread可执行文件,输入./thread即可。

  1. [test@localhost Desktop]$ ./thread
  2. this is func_1!
  3. this is func_2!
  4. this is func_1!
  5. this is func_1!
  6. this is func_2!
  7. this is func_1!
  8. this is func_1!
  9. this is func_2!
  10. this is func_1!
  11. this is func_1!

=================================================================

linux下的C语言开发(管道通信)

Linux系统本身为进程间通信提供了很多的方式,比如说管道、共享内存、socket通信等。管道的使用十分简单,在创建了匿名管道之后,我们只需要从一个管道发送数据,再从另外一个管道接受数据即可。

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. int pipe_default[2];
  6. int main()
  7. {
  8. pid_t pid;
  9. char buffer[32];
  10. memset(buffer, 0, 32);
  11. if(pipe(pipe_default) < 0)
  12. {
  13. printf("Failed to create pipe!\n");
  14. return 0;
  15. }
  16. if(0 == (pid = fork()))
  17. {
  18. close(pipe_default[1]);
  19. sleep(5);
  20. if(read(pipe_default[0], buffer, 32) > 0)
  21. {
  22. printf("Receive data from server, %s!\n", buffer);
  23. }
  24. close(pipe_default[0]);
  25. }
  26. else
  27. {
  28. close(pipe_default[0]);
  29. if(-1 != write(pipe_default[1], "hello", strlen("hello")))
  30. {
  31. printf("Send data to client, hello!\n");
  32. }
  33. close(pipe_default[1]);
  34. waitpid(pid, NULL, 0);
  35. }
  36. return 1;
  37. }

下面我们就可以开始编译运行了,老规矩分成两步骤进行:(1)输入gcc pipe.c -o pipe;(2)然后输入./pipe,过一会儿你就可以看到下面的打印了。

  1. [test@localhost pipe]$ ./pipe
  2. Send data to client, hello!
  3. Receive data from server, hello!

=====================================================================

 linux下的C语言开发(信号处理)
 

信号处理是Linux程序的一个特色。用信号处理来模拟操作系统的中断功能,对于我们这些系统程序员来说是最好的一个选择了。要想使用信号处理功能,你要做的就是填写一个信号处理函数即可。一旦进程有待处理的信号处理,那么进程就会立即进行处理。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <signal.h>
  4. int value = 0;
  5. void func(int sig)
  6. {
  7. printf("I get a signal!\n");
  8. value = 1;
  9. }
  10. int main()
  11. {
  12. signal(SIGINT, func);
  13. while(0 == value)
  14. sleep(1);
  15. return 0;
  16. }

为了显示linux对signal的处理流程,我们需要进行两个步骤。第一,输入gcc sig.c -o sig, 然后输入./sig即可;第二则重启一个console窗口,输入ps -aux | grep sig, 在获取sig的pid之后然后输入kill -INT 2082, 我们即可得到如下的输出。

  1. [root@localhost fork]#./sig
  2. I get a signal!
  3. [root@localhost fork]#

===========================================================

 linux下的C语言开发(进程等待)

所谓进程等待,其实很简单。前面我们说过可以用fork创建子进程,那么这里我们就可以使用wait函数让父进程等待子进程运行结束后才开始运行。注意,为了证明父进程确实是等待子进程运行结束后才继续运行的,我们使用了sleep函数。但是,在Linux下面,sleep函数的参数是秒,而windows下面sleep的函数参数是毫秒。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. int main(int argc, char* argv[])
  5. {
  6. pid_t pid;
  7. pid = fork();
  8. if(0 == pid)
  9. {
  10. printf("This is child process, %d\n", getpid());
  11. sleep(5);
  12. }
  13. else
  14. {
  15. wait(NULL);
  16. printf("This is parent process, %d\n", getpid());
  17. }
  18. return 1;
  19. }

下面,我们需要做的就是两步,首先输入gcc fork.c -o fork, 然后输入./fork,就会在console下面获得这样的结果。

  1. [root@localhost fork]# ./fork
  2. This is child process, 2135
  3. This is parent process, 2134
 
 ===================================================
linux下的C语言开发(线程等待)

和多进程一样,多线程也有自己的等待函数。这个等待函数就是pthread_join函数。那么这个函数有什么用呢?我们其实可以用它来等待线程运行结束。

  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. void func(void* args)
  6. {
  7. sleep(2);
  8. printf("this is func!\n");
  9. }
  10. int main()
  11. {
  12. pthread_t pid;
  13. if(pthread_create(&pid, NULL, func, NULL))
  14. {
  15. return -1;
  16. }
  17. pthread_join(pid, NULL);
  18. printf("this is end of main!\n");
  19. return 0;
  20. }

编写wait.c文件结束之后,我们就可以开始编译了。首先你需要输入gcc wait.c -o wait -lpthread,编译之后你就可以看到wait可执行文件,输入./wait即可。

  1. [test@localhost thread]$ ./thread
  2. this is func!
  3. this is end of main!
 
 =====================================================
linux下的C语言开发(线程互斥)

对于编写多线程的朋友来说,线程互斥是少不了的。在Linux下面,编写多线程常用的工具其实是pthread_mutex_t。本质上来说,它和Windows下面的mutex其实是一样的,差别几乎是没有。希望对线程互斥进行详细了解的朋友可以看这里

  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. static int value = 0;
  6. pthread_mutex_t mutex;
  7. void func(void* args)
  8. {
  9. while(1)
  10. {
  11. pthread_mutex_lock(&mutex);
  12. sleep(1);
  13. value ++;
  14. printf("value = %d!\n", value);
  15. pthread_mutex_unlock(&mutex);
  16. }
  17. }
  18. int main()
  19. {
  20. pthread_t pid1, pid2;
  21. pthread_mutex_init(&mutex, NULL);
  22. if(pthread_create(&pid1, NULL, func, NULL))
  23. {
  24. return -1;
  25. }
  26. if(pthread_create(&pid2, NULL, func, NULL))
  27. {
  28. return -1;
  29. }
  30. while(1)
  31. sleep(0);
  32. return 0;
  33. }

编写mutex.c文件结束之后,我们就可以开始编译了。首先你需要输入gcc mutex.c -o mutex -lpthread,编译之后你就可以看到mutex可执行文件,输入./mutex即可。

  1. [test@localhost thread]$ ./mutex
  2. value = 1!
  3. value = 2!
  4. value = 3!
  5. value = 4!
  6. value = 5!
  7. value = 6!

=======================================================

linux下的C语言开发(网络编程)

不管在Windows平台下面还是在Linux平台下面,网络编程都是少不了的。在互联网发达的今天,我们的生活基本上已经离不开网络了。我们可以用网络干很多的事情,比如说IM聊天、FTP下载、电子银行、网络购物、在线游戏、电子邮件的收发等等。所以说,对于一个软件的开发者来说,如果说他不会进行网络程序的开发,那真是难以想象的。

在开始介绍网络编程的方法之前,我们可以回忆一下计算机网络的相关知识。目前为止,我们使用的最多网络协议还是tcp/ip网络。通常来说,我们习惯上称为tcp/ip协议栈。至于协议栈分成几层,有两种说法。一种是五层,一种是七层,我个人本身也比较倾向于五层的划分方法。大家可以通过下面的图看看协议栈是怎么划分的。

5、应用层
    4、传输层
    3、网络层
    2、数据链路层
    1、物理层

网络的不同层次实现网络的不同功能。物理层主要实现报文的成帧处理;数据链路层完成对报文的优先级的管理,同时实现二层转发和流量控制;网络层实现路由和转发的功能,一方面它需要实现对报文的fragment处理,另外一方面它还需要对路由信息进行处理和保存;传输层实现报文的发送和接受,它利用计数、时序、定时器、重发等机制实现对报文的准确发送,当然这都是tcp的发送机制,而udp一般是不保证报文正确发送和接收的;应用层就是根据传输层的端口信息调用不同的程序来处理传输的内容,端口8080是http报文,端口21是ftp报文等等。上面的逻辑稍显复杂,朋友们可以这么理解,

物理层关心的是如何把电气信号变成一段报文;数据链路层关心的是mac地址、vlan、优先级等;网络层关心的是ip地址,下一跳ip;传输层关心的是端口资源;应用层关心的是报文组装、解析、渲染、存储、执行等等。

目前关于tcp/ip完整协议栈的代码很多,其中我认为写得比较好的还是linux内核/net/ipv4下面的代码。如果朋友们对ipv6的代码感兴趣,也可以看看/net/ipv6的代码。档案如果朋友们对整个协议栈的代码结构理解得不是很清楚,可以参考《linux网络分析与开发》这本书。

当然,作为应用层,我们的其实考虑的不用这么复杂。对于网络程序编写人员来讲,所有网络的资源只要和一个socket关联在一起就可以了。当然在socket可用之前,我们需要为它配置端口信息和ip地址。配置完了之后,我们就可以慢慢等待报文的收发了。所以一般来说,作为服务器端口的处理流程是这样的,

a) 创建socket
    b) 绑定socket到特定的ip地址
    c) 对socket进行侦听处理
    d) 接受socket,表明有客户端和服务器连接
    e) 和客户端循环收发报文
    f) 关闭socket

作为服务器程序而言,它要对特定的端口进行绑定和侦听处理,这样稍显复杂。但是如果是编写客户端的程序,一切的一切就变得非常简单了,

   a) 创建socket
    b) 链接服务器端地址
    c) 和服务器端的socket收发报文

上面只是对网络编程做了一个基本的介绍,但是好多的东西还是没有涉及到,比如说:(1) 什么时候该使用udp,什么时候该使用tcp?(2) 如何把多线程和网络编程联系在一起? (3) 如何把多进程和网络编程联系在一起? (4) 如何利用select函数、epoll_create机制、非阻塞函数提高socket的并发处理效率? (5) linux内核是怎么实现tcp/ip协议的? (6) 我们自己是否也可以实现协议的处理流程等等?

 
 
 

linux下的C语言开发 进程创建 延伸的几个例子的更多相关文章

  1. linux下的C语言开发

    在很多人的眼里,C语言和linux常常是分不开的.这其中的原因很多,其中最重要的一部分我认为是linux本身就是C语言的杰出作品.当然,linux操作系统本身对C语言的支持也是相当到位的.作为一个真正 ...

  2. linux下的C语言开发 GDB的例子

    在很多人的眼里,C语言和linux常常是分不开的.这其中的原因很多,其中最重要的一部分我认为是linux本身就是C语言的杰出作品.当然,linux操作系统本身对C语言的支持也是相当到位的.作为一个真正 ...

  3. linux下的C语言开发(网络编程)

    http://blog.csdn.net/feixiaoxing/article/details/7259675 [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing ...

  4. linux下的C语言开发(定时器)

    定时器是我们需要经常处理的一种资源.那Linux下面的定时器又是怎么一回事呢?其实,在linux里面有一种进程中信息传递的方法,那就是信号.这里的定时器就相当于系统每隔一段时间给进程发一个定时信号,我 ...

  5. linux下的C语言开发(静态库/动态库)

    动态链接库不是Linux独有的特性,在windows下面也存在这样的特性.一般来说,windows下面的动态连接库是以*.dll作为结尾的,而linux下面的动态连接库是以*.so结尾的.和静态链接库 ...

  6. linux下的C语言开发(gdb调试)

    原文: http://blog.csdn.net/feixiaoxing/article/details/7199643 用gdb调试多进程的程序会遇到困难,gdb只能跟踪一个进程(默认是跟踪父进程) ...

  7. 在 Linux 下学习 C 语言有什么好处?

    作者:宅学部落链接:https://www.zhihu.com/question/23893390/answer/832610610来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...

  8. Linux学习心得之 Linux下命令行Android开发环境的搭建

    作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 Linux学习心得之 Linux下命令行Android开发环境的搭建 1. 前言2. Jav ...

  9. Linux 下 expect 脚本语言中交互处理常用命令

    Linux 下 expect 脚本语言中交互处理常用命令 1. #!/usr/bin/expect 告诉操作系统脚本里的代码使用那一个 shell 来执行.这里的 expect 其实和 Linux 下 ...

随机推荐

  1. LINUX系统---中级相关操作和知识

    LINUX系统的中级,来搞一些LINUX安全相关的东西,还有在公司生成中长搞的集群. RHCS集群 什么是高可用 什么是热备 什么是分布式

  2. 6.0以上,SYSTEM_ALERT_WINDOW 权限的问题

    6.0以上会因为SYSTEM_ALERT_WINDOW权限的问题,无法在最上层显示. 用户打开软件设置页手动打开,才能授权.路径是:Settings->Apps->App Setting- ...

  3. 第五章、 Linux 常用網路指令

    http://linux.vbird.org/linux_server/0140networkcommand.php     第五章. Linux 常用網路指令 切換解析度為 800x600 最近更新 ...

  4. node.js 写流 createWriteStream----由浅入深

    createWriteStream 写流 基于fs模块 let fs=require("fs"); createWriteStream创建一个写流 我们先创建一个2.txt要写入的 ...

  5. android中后一个activity传值给前一个activity的实现

    前一个activity跳转到后一个activity设置code: Intent intent=new Intent(MainActivity.this,ActivityTwo.class); star ...

  6. [bzoj3879]SvT_后缀数组_RMQ_单调栈

    SvT bzoj-3879 题目大意:给定一个字符串.每次询问给定$t$个位置,求两两位置开头的后缀的$LCP$之和. 注释:$1\le length\le 5\cdot 10^5$,$\sum t\ ...

  7. org.springframework.amqp.AmqpIOException: java.net.UnknownHostException: guest解决

    org.springframework.amqp.AmqpIOException: java.net.UnknownHostException: guest 由于在yml文件中配置的时候误将passw ...

  8. SHARP 加粉

    http://v.ku6.com/show/7ufwm7pqfF8D_f13IdCaag...html

  9. hadoop 文件操作

    Create a directory in HDFS - mkdir The hadoop mkdir command is for creating directories in the hdfs. ...

  10. 运行shell脚本报错 &#39;\357\273\277&#39;: command not found 解决的方法

    1,删除BOM,在vi以下运行以下的命令就可以 :set nobomb 2,原因: 所谓BOM,全称是Byte Order Mark.它是一个Unicode字符,通常出如今文本的开头,用来标识字节序( ...