当前位置: 首页 > news >正文

从函数调用到进程通信:Linux下的多语言协作实践

目录

程序间调用的优势之一

1、Shell脚本

脚本功能说明:

执行效果

使用方法:

2、Python 脚本 (python.py)

功能说明:

使用方法:

输出:

3、C++ 程序 (test.cc)

功能说明:

编译与运行:

输出:

4、三者的对比总结

补充说明

程序替换

C 程序 (proc.c)

功能说明

编译与运行

对比表格

总结


        当你掌握了C语言、C++或Java等高级语言时,你可能仅了解函数间的相互调用。但随着深入学习进程相关知识,你会发现程序之间同样可以实现相互调用。在学习新内容之前,我们先探讨函数与进程的相似性。exec/exit 机制类似于函数调用中的 call/return 模式。

以C语言为例,你应该掌握以下核心概念:

  1. 一个C程序由多个函数构成,函数之间可以相互调用并传递参数
  2. 被调函数执行特定操作后会返回结果值
  3. 每个函数都拥有独立的局部变量空间
  4. 函数间通过call/return机制进行通信

        这种基于参数传递和返回值、在保持数据私密性的函数间进行通信的模式,构成了结构化程序设计的基础。Linux系统将这种程序内部的设计理念进一步扩展到了程序间的交互中,如下图所示:

        通过fork系统调用,父进程可以创建子进程。随后使用exec系列函数,子进程能够加载并执行其他程序,替换原有代码和数据,子进程通过exit(n)返回状态值,父进程则通过wait(&ret)系统调用获取子进程的退出状态。这种机制实现了程序间的调用与切换。

pid_t id = fork();
if (id == 0){execvp(myargv[0], myargv);exit(1);
}

        程序执行完毕后,会通过exit(n)返回一个状态值。调用进程可使用waitwaitpid函数来获取该返回值。

wait(&status);
waitpid(id, &status, 0);

程序间调用的优势之一

        不同编程语言各有其特长,在实际开发中,我们常需要组合使用多种语言。通过程序间的相互调用,就能实现不同语言的无缝衔接。

例如,C程序可以通过exec系列函数来调用Shell脚本、Python或C++等语言编写的程序。

1、Shell脚本

这是一个简单的 Bash 脚本文件 test.sh,内容如下:

#!/bin/bashi=0
while [ $i -le 10 ]
doecho "hello shell:$i"let i++
done

脚本功能说明:

  1. #!/bin/bash:指定脚本使用 Bash 解释器执行。

  2. i=0:初始化变量 i 的值为 0。

  3. while [ $i -le 10 ]:当 i 的值小于或等于 10 时,循环继续执行。

  4. echo "hello shell:$i":打印字符串 hello shell: 并附带当前 i 的值。

  5. let i++:每次循环结束后,将 i 的值加 1。

  6. done:标记循环结束。

执行效果

        运行此脚本会输出 11 行内容(从 i=0 到 i=10),每行格式为 hello shell: 后跟当前循环计数器的值。

使用方法:

  1. 将脚本保存为 test.sh

  2. 赋予执行权限:chmod +x test.sh

  3. 运行脚本:./test.sh

输出示例:

2、Python 脚本 (python.py)

#!/usr/bin/pythonprint("hello python!")
功能说明
  • #!/usr/bin/python:指定脚本使用 Python 解释器执行。

  • print("hello python!"):打印字符串 hello python!

使用方法
  1. 将脚本保存为 python.py

  2. 赋予执行权限(可选):chmod +x python.py

  3. 运行脚本:

    • 直接执行:./test.py(需确保 Python 路径正确)。

    • 或通过 Python 解释器运行:python python.py

输出

3、C++ 程序 (test.cc)

#include <iostream>
using namespace std;int main()
{cout << "hello C++" << endl;return 0;
}
功能说明
  • #include <iostream>:引入标准输入输出库。

  • using namespace std:使用标准命名空间,避免重复写 std::

  • cout << "hello C++" << endl:打印字符串 hello C++ 并换行。

  • return 0:表示程序正常退出。

编译与运行
  1. 将代码保存为 test.cc

  2. 编译(需安装 g++):

    g++ test.cc -o test
  3. 运行生成的可执行文件:

    ./test
输出

4、三者的对比总结

特性Bash 脚本Python 脚本C++ 程序
文件扩展名.sh.py.cc 或 .cpp
执行方式解释执行(直接或通过 Bash)解释执行(直接或通过 Python)需编译后运行二进制文件
语法复杂度简单(面向命令)简洁(高级抽象)复杂(需管理内存、类型等)
性能低(依赖系统 Shell)中等(解释器开销)高(直接编译为机器码)
典型用途系统管理、自动化任务快速开发、脚本工具高性能应用、底层开发
依赖需 Bash 环境需 Python 环境需编译器(如 g++)

补充说明

  • Bash 脚本 (test.sh):适用于 Linux/Unix 系统自动化任务,无需编译,直接解释执行。

  • Python 脚本 (test.py):跨平台,适合快速开发,解释执行,依赖 Python 环境。

  • C++ 程序 (test.cc):高性能场景,需编译(如 g++ test.cc -o test),生成可执行文件后运行。

程序替换

我们使用以下C程序,便可以分别调用以上三个程序:

C 程序 (proc.c)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>int main() {pid_t id = fork();if (id == 0) {// 子进程execl("./test.sh", "test.sh", NULL);  // 调用 Bash 脚本// execl("./python.py", "python.py", NULL); // 调用 Python 脚本// execl("./test", "test", NULL);       // 调用 C++ 程序exit(1);  // 若 execl 失败则退出}// 父进程等待子进程结束int status = 0;pid_t ret = waitpid(id, &status, 0);if (ret > 0) {printf("exit code: %d\n", WEXITSTATUS(status));}return 0;
}

功能说明

  1. 多进程控制

    • 使用 fork() 创建子进程,子进程通过 execl() 调用外部程序。

    • 父进程通过 waitpid() 等待子进程结束,并获取其退出状态码。

  2. 调用方式

    • Bash 脚本execl("./test.sh", "test.sh", NULL)

    • Python 脚本execl("./python.py", "python.py", NULL)(需取消注释)

    • C++ 程序execl("./test", "test", NULL)(需先编译 test.cc 生成 test

  3. 注意事项

    • 被调用的程序(如 test.shpython.pytest)需具有可执行权限。

    • 若 execl() 调用失败,子进程会执行 exit(1),父进程捕获的退出码为 1

编译与运行

  1. 编译 C 程序

    gcc proc.c -o proc
  2. 运行程序

    ./proc
  3. 输出示例: 

调用shell脚本运行结果: 

调用python运行结果: 

调用C++运行结果: 

对比表格

调用目标语言需提前准备C 中调用方法
test.shBash赋予执行权限 (chmod +x)execl("./test.sh", "test.sh", NULL)
test.pyPython确保 Python 环境可用execl("./python.py", "python.py", NULL)
testC++编译生成可执行文件 (g++)execl("./test", "test", NULL)

总结

  • 用途:该 C 程序通过进程管理实现了对多种语言脚本/程序的灵活调用,适用于需要混合编程的场景(如用 C 控制任务流程,调用其他语言模块)。

  • 扩展性:可通过修改 execl() 参数调用其他外部程序(如 Perl、Java 等)。

http://www.lryc.cn/news/590578.html

相关文章:

  • 识别装甲板
  • 【Jupyter】个人开发常见命令
  • HugeGraph 【图数据库】JAVA调用SDK
  • ByteToMessageDecoder详解
  • Spring AI快速入门
  • VisualVM监控远程Linux的java进程
  • 【SpringBoot】实战-开发接口-用户-注册
  • matlab的伯德图为何从360度显示?应如何修改解决?
  • 基于大数据的网络文学推荐分析系统的设计与实现【海量书籍、自动爬虫】
  • Redis1:高并发与微服务中的键值存储利器
  • mongodb操作巨鹿
  • DHTMLX Suite 9.2 重磅发布:支持历史记录、类Excel交互、剪贴板、拖放增强等多项升级
  • Qt小组件 - 6 异步运行函数
  • Redis深度解析:从缓存到分布式系统的核心引擎
  • Java高并发编程(2)
  • beautiful-react-hooks库——入门实践常用hook详解
  • React之旅-09 useMemo,优化计算性能的利器
  • React 源码7:Lane、React和schedule优先级转换
  • WPF 多窗口分文件实现方案
  • 【MAC】nacos 2.5.1容器docker安装
  • QT——事件系统详解
  • 多语言json文件内\n换行不生效问题
  • React -自定义hooks - 封装双向数据绑定
  • React 中 props 的最常用用法精选+useContext
  • H3CNE综合实验之机器人
  • Antd中使用Table集成 react-resizable实现可伸缩列
  • PowerJob集群机器数为0问题
  • 深度剖析 TDMQ RabbitMQ 版经典队列底层存储机制
  • vue页面不销毁的情况下再返回,总是执行created,而不触发 activated
  • QOpenGLWidget自定义控件— 2D点云显示(支持平移、放缩、绘制网格)