system()函数 http://blog.youkuaiyun.com/ghevinn/article/details/7916126

system()函数功能强大,很多人用却对它的原理知之甚少先看linux版system函数的源码:


#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <unistd.h>

int system(const char * cmdstring)

{
    pid_t pid;
    int status;

    if(cmdstring == NULL){
           
         return (1);
    }


    if((pid = fork())<0){

            status = -1;
    }


    else if(pid = 0){

        execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);

        -exit(127); //子进程正常执行则不会执行此语句

        }

    else{

            while(waitpid(pid, &status, 0) < 0){

                if(errno != EINTER){

                    status = -1;

                    break;

                }

            }

        }


        return status;


}


先分析一下原理,然后再看上面的代码大家估计就能看懂了:   
    当system接受的命令为NULL时直接返回,否则fork出一个子进程,因为fork在两个进程:父进程和子进程中都返回,这里要检查返回的pid,fork在子进程中返回0,在父进程中返回子进程的pid,父进程使用waitpid等待子进程结束,子进程则是调用execl来启动一个程序代替自己,execl("/bin/sh", "sh", "-c", cmdstring, (char*)0)是调用shell,这个shell的路径是/bin/sh,后面的字符串都是参数,然后子进程就变成了一个shell进程,这个shell的参数
是cmdstring,就是system接受的参数。在windows中的shell是command,想必大家很熟悉shell接受命令之后做的事了。
   
如果上面的你没有看懂,那我再解释下fork的原理:当一个进程A调用fork时,系统内核创建一个新的进程B,并将A的内存映像复制到B的进程空间中,因为A和B是一样的,那么他们怎么知道自己是父进程还是子进程呢,看fork的返回值就知道,上面也说了fork在子进程中返回0,在父进程中返回子进程的pid。

    windows中的情况也类似,就是execl换了个又臭又长的名字,参数名也换的看了让人发晕的,我在MSDN中找到了原型,给大家看看:

HINSTANCE   ShellExecute(
               HWND   hwnd,
               LPCTSTR   lpVerb,
               LPCTSTR   lpFile,
               LPCTSTR   lpParameters,
               LPCTSTR   lpDirectory, 
               INT   nShowCmd 
   );   

      用法见下:

     ShellExecute(NULL,   "open",   "c:\\a.reg",   NULL,   NULL,   SW_SHOWNORMAL);   


    你也许会奇怪 ShellExecute中有个用来传递父进程环境变量的参数 lpDirectory,linux中的 execl却没有,这是因为execl是编译器的函数(在一定程度上隐藏具体系统实现),在linux中它会接着产生一个linux系统的调用 execve, 原型见下:
    int execve(const char * file,const char **argv,const char **envp);
   
    看到这里你就会明白为什么system()会接受父进程的环境变量,但是用system改变环境变量后,system一返回主函数还是没变。原因从system的实现可以看到,它是通过产生新进程实现的,从我的分析中可以看到父进程和子进程间没有进程通信,子进程自然改变不了父进程的环境变量。希望小菜们不要拿tc或使用tc库的其他编译器中的system的调用结果来反驳我,这不是一个概念,DOS早死翘翘了,玩linux吧。

版权声明:本文为博主原创文章,未经博主允许不得转载。

根据你提供的链接([https://shylss.blog.csdn.net/article/details/148999625](https://shylss.blog.csdn.net/article/details/148999625)),该文章主题为 **“Simulink自动生成嵌入式C代码并集成到Keil工程”**,重点是使用 Simulink 的 Embedded Coder 功能将模型自动转换为 C 代码,并将其部署到 Keil MDK 环境中用于 STM32 等嵌入式系统。 但你的需求是: 👉 **“自动生成 MATLAB 工程,要求是一个 .m 文件”** 这可能存在理解偏差。因为: - “自动生成 MATLAB 工程” —— MATLAB 并没有像 Visual Studio 那样的 `.sln` 工程文件概念,通常一个 MATLAB 项目由多个 `.m`、`.mat`、`.fig` 等文件组成,可通过 `.prj` 文件管理(R2021a+ 支持 Project 工具)。 - “要求是一个 .m 文件” —— 这更可能是指:**写一个单一的 MATLAB 脚本文件(.m)来实现某项自动化任务,比如生成 Simulink 模型或配置代码生成设置。** --- ### ✅ 推测你的实际需求: 你想通过一个 `.m` 脚本文件,**自动创建一个 Simulink 模型,并配置其代码生成参数,以便后续能自动生成嵌入式 C 代码(如文章所述)**。 下面我将为你提供这样一个 **完整的 MATLAB 脚本(.m 文件)示例**,它可以: 1. 创建一个新的 Simulink 模型 2. 添加基本模块(如 Sine Wave, Gain, Outport) 3. 设置模型用于代码生成(Embedded Coder / GRT Target) 4. 保存模型和脚本 --- ```matlab %% 自动化生成 Simulink 模型并配置代码生成 - save as generate_simulink_project.m % % 作者:MATLAB Expert % 功能:自动生成 Simulink 模型,配置代码生成选项,适用于嵌入式C生成 % 输出:model_auto.slx + 配置好的代码生成设置 function generate_simulink_project() % 启动 Simulink 环境 slclear; % 清除旧模型缓存 simulink; % 打开 Simulink 库(可选) modelName = 'model_auto'; % ================= 第一步:新建或打开模型 ================= if ~exist(modelName, 'file') new_system(modelName, 'Model'); % 创建新模型 else close_system(modelName, 0); % 关闭已存在的同名模型 load_system(modelName); end open_system(modelName); % ================= 第二步:添加模块 ================= % 添加 Sine Wave 模块 add_block('simulink/Sources/Sine Wave', [modelName '/Sine']); % 添加 Gain 模块 add_block('simulink/Math Operations/Gain', [modelName '/Gain'], ... 'Position', [280, 105, 340, 135], 'Gain', '2'); % 添加 Outport add_block('simulink/Sinks/Out1', [modelName '/Out1'], ... 'Position', [420, 110, 440, 130]); % ================= 第三步:连接模块 ================= add_line(modelName, 'Sine/1', 'Gain/1'); % Sine -> Gain add_line(modelName, 'Gain/1', 'Out1/1'); % Gain -> Out1 % ================= 第四步:设置模型参数以支持代码生成 ================= set_param(modelName, 'SystemTargetFile', 'grt.tlc'); % 使用 GRT (Generic Real-Time) set_param(modelName, 'RTWVerbose', 'false'); % 关闭详细构建日志 set_param(modelName, 'GenerateCodeOnly', 'on'); % 只生成代码 set_param(modelName, 'HardwareBoard', ''); % 不指定具体硬件板 set_param(modelName, 'TargetLang', 'C'); % 目标语言为 C set_param(modelName, 'GenCodeOnlyTemplateMakefile', 'grt_linux.tmf'); % 或 grt_accel.tmf 等 % 可选:启用嵌入式编码器(如果有 Embedded Coder) try set_param(modelName, 'Product', 'Embedded Coder'); catch warning('Embedded Coder 未激活,使用 Simulink Coder 默认设置。'); end % ================= 第五步:保存模型 ================= save_system(modelName); disp(['模型已保存为: ', modelName, '.slx']); % ================= 第六步:提示如何生成代码 ================= fprintf('\n'); fprintf('✅ 模型 "%s" 创建完成!\n', modelName); fprintf('📌 要生成C代码,请在命令行运行:\n'); fprintf(' >> rtwbuild(''%s'')\n', modelName); end ``` --- ### 🔍 上述代码解释: | 部分 | 说明 | |------|------| | `new_system` | 创建新的空白 Simulink 模型 | | `add_block` | 插入模块(来自 Simulink 库浏览器路径) | | `add_line` | 连接两个模块的端口 | | `set_param(..., 'SystemTargetFile', 'grt.tlc')` | 设置目标为“通用实时系统”,会生成独立 C 代码 | | `GenerateCodeOnly` | 表示不编译,只生成代码 | | `rtwbuild()` | 是后续手动或脚本调用的函数,用于真正生成代码 | > ⚠️ 注意:要成功生成 C 代码,你需要安装 **Simulink Coder** 或 **Embedded Coder** 工具箱。 --- ### 🧪 使用方法: 1. 将上面代码保存为文件:`generate_simulink_project.m` 2. 在 MATLAB 命令窗口运行: ```matlab generate_simulink_project ``` 3. 它会生成 `model_auto.slx` 4. 再运行: ```matlab rtwbuild('model_auto') ``` 即可在 `model_auto_ert_rtw` 文件夹中看到生成的 `.c` 和 `.h` 文件。 --- ### ✅ 适用场景: - 快速搭建标准 Simulink 模型模板 - 自动化 CI/CD 流程中的模型初始化 - 教学演示自动化建模流程 - 与外部工具链(如 Keil、IAR)集成前的准备阶段 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值