在学了C语言、C++或是JAVA等高级语言,你会知道,在这些语言中的函数是可以相互进行见调用的,但是在学习了Linux的前面的知识后,你就会有意无意的认识到其实进程也是与函数有相同之处的,进程之间也是可以相互调用的。
如果你学过C语言,你应该有以下认识:
- 一个C程序由很多函数组成,一个函数可以调用另一个函数,同时传递给它一些参数。
- 同样main函数也是如此
- 被调用的函数会执行一定的操作,然后通过特定的操作返回一个值。
- 每个函数都有它自己的局部变量,也会有自己独立的存储空间。
- 不同函数在汇编语言中通过call/return系统进行“通信”。
c语言中的函数通过参数和返回值,在拥有私有数据的函数间“通信”的模式是结构化程序设计的基础,Linux鼓励将这种应用于程序之内的模式扩展到程序之间。
在一个C程序可以fork/exec另一个程序,其过程是先fork一个子进程,然后让子进程使用exec系列函数将子进程的代码和数据替换为另一个程序的代码和数据,之后子进程就用该程序的数据执行该程序的代码,从而达到程序之间相互调用的效果。
pid_t id = fork();
if (id == 0){
execvp(proc[0], myargv);
exit(1);
}
当这个被调用的程序执行完毕后,通过exit(n)来返回一个值。调用它的进程可以通过wait或waitpid来获取这个返回值(避免僵尸进程)。
wait(&status);
waitpid(id, &status, 0);
那这时候就要说了,这在前面的内容中多少都已经了解,那么这里为什么又进行提到了呢?这里又有什么特别之处吗?
那么下面就将这部分内容扩展。
程序之间相互调用带来的好处之一
这里就扩展一个小知识:大多数现代游戏并不是用单一语言开发的! 游戏开发是一个复杂的工程,通常需要利用多种语言的优势,以实现高性能、跨平台性以及开发效率的最佳平衡。
他可能说是用C 和 C++作为核心性能语言。C#作为脚本语言(Unity 中常见)Python作为工具开发、AI 和脚本......
那么我们在C语言中也应该可以用fork/exec系列函数调用shell脚本、python以及C++等语言实现的程序,来进行上述类似操作。
比如下面的操作:
我们先在同一目录下创建如下的文件:
然后在对应的文件内添加如下的代码:
Shell 脚本(script.sh)
#!/bin/bash echo "Hello from Shell Script!"
Python 脚本(script.py )
print("Hello from Python Script!")
C 语言程序(main.c)
#include <stdio.h> #include <stdlib.h> int main() { // 调用 Shell 脚本 printf("Calling Shell Script...\n"); int shell_status = system("./script.sh"); if (shell_status == 0) { printf("Shell Script executed successfully.\n"); } else { printf("Failed to execute Shell Script.\n"); } // 调用 Python 脚本 printf("\nCalling Python Script...\n"); int python_status = system("python3 script.py"); if (python_status == 0) { printf("Python Script executed successfully.\n"); } else { printf("Failed to execute Python Script.\n"); } return 0; }
然后在Xshell中运行下面的指令:
赋予bash执行权限:
chmod +x script.sh
编译 C 语言程序
gcc main.c -o main
运行程序
./main
输出效果:
原理解析
system() 函数:
system()
是一个标准 C 库函数,用于执行系统命令。system("./script.sh")
调用 Shell 脚本。system("python3 script.py")
调用 Python 脚本。
脚本可执行权限:
- Shell 脚本需要设置可执行权限(
chmod +x script.sh
)。 - Python 脚本则通过
python3
解释器执行。
- Shell 脚本需要设置可执行权限(
返回值检查:
system()
返回 0 表示命令成功执行,非 0 表示执行失败。