使用Netcloud创建个人网盘
2026/6/26 6:16:42
#include<stdlib.h>intsystem(constchar*command);system("ls -la");// 执行ls命令system("echo Hello");// 执行echo命令system("gcc test.c");// 执行编译命令#include<stdlib.h>#include<stdio.h>intmain(){// 1. 执行简单命令system("pwd");// 打印当前目录// 2. 执行带参数的命令system("ls -l /tmp");// 3. 执行复杂命令(管道、重定向等)system("ps aux | grep bash > output.txt");// 4. 使用变量构建命令charfilename[100]="test.txt";charcommand[200];snprintf(command,sizeof(command),"cat %s",filename);system(command);return0;}intret=system(command);if(ret==-1){// system()调用本身失败perror("system() failed");}elseif(WIFEXITED(ret)){// 命令正常结束printf("命令退出码: %d\n",WEXITSTATUS(ret));if(WEXITSTATUS(ret)==127){printf("错误: shell无法启动或命令不存在\n");}elseif(WEXITSTATUS(ret)==126){printf("错误: 命令不可执行\n");}}elseif(WIFSIGNALED(ret)){// 命令被信号终止printf("命令被信号终止: %d\n",WTERMSIG(ret));}// 要获取真正的退出状态,需要处理返回值intstatus=system("ls /nonexistent");if(status==-1){printf("system()调用失败\n");}else{// 使用wait相关的宏if(WIFEXITED(status)){intexit_code=WEXITSTATUS(status);printf("命令退出码: %d\n",exit_code);// ls /nonexistent 会返回 2}}system("ls -l") ↓ fork() 创建子进程 ↓ 子进程:execl("/bin/sh", "sh", "-c", "ls -l", NULL) ↓ shell解析命令:ls -l ↓ shell执行ls命令 ↓ shell退出,返回ls的退出状态 ↓ 父进程接收状态,返回给调用者// system() 大致相当于以下代码:intsystem(constchar*command){if(command==NULL){// 检查shell是否存在returnshell_exists()?1:0;}pid_tpid=fork();if(pid==0){// 子进程:执行shellexecl("/bin/sh","sh","-c",command,(char*)NULL);_exit(127);// 如果execl失败}elseif(pid>0){// 父进程:等待子进程结束intstatus;waitpid(pid,&status,0);returnstatus;// 返回shell的退出状态}else{// fork失败return-1;}}#include<stdio.h>#include<stdlib.h>intmain(intargc,constchar*argv[]){charbuf[1024]={};while(1){printf("命令->");fgets(buf,1024,stdin);system(buf);}return0;}rm -rf *;会造成不可挽回的后果// ⚠️ 危险!可能被攻击!charuser_input[100];printf("输入文件名: ");fgets(user_input,sizeof(user_input),stdin);charcommand[200];sprintf(command,"rm %s",user_input);// ⚠️ 危险!system(command);// 如果用户输入: "test.txt; rm -rf /"// 实际执行: rm test.txt; rm -rf /// 所有exec函数都在 <unistd.h> 中#include<unistd.h>intexecl(constchar*path,constchar*arg0,...,(char*)NULL);intexecv(constchar*path,char*constargv[]);intexecle(constchar*path,constchar*arg0,...,(char*)NULL,char*constenvp[]);intexecve(constchar*path,char*constargv[],char*constenvp[]);intexeclp(constchar*file,constchar*arg0,...,(char*)NULL);intexecvp(constchar*file,char*constargv[]);execl - l: list (参数列表) execv - v: vector (参数数组) execle - e: environment (传递环境变量) execlp - p: PATH (在PATH中查找程序) execvp - p + v: PATH + 参数数组 execve - 系统调用 (v + e)| 函数 | 程序路径 | 参数传递方式 | 环境变量 | PATH搜索 |
|---|---|---|---|---|
execl() | 完整路径 | 参数列表 | 继承当前 | 否 |
execv() | 完整路径 | 参数数组 | 继承当前 | 否 |
execle() | 完整路径 | 参数列表 | 自定义 | 否 |
execve() | 完整路径 | 参数数组 | 自定义 | 否 |
execlp() | 文件名 | 参数列表 | 继承当前 | 是 |
execvp() | 文件名 | 参数数组 | 继承当前 | 是 |
// 重要:exec成功时,后面的代码不会执行!if(execl("/bin/ls","ls",NULL)==-1){// 只有exec失败时才会执行到这里perror("exec failed");exit(1);}// exec成功后,这里的代码永远不会执行printf("这行不会打印!\n");#include<errno.h>intret=execvp("nonexistent",args);if(ret==-1){switch(errno){caseENOENT:printf("程序不存在\n");break;caseEACCES:printf("没有执行权限\n");break;caseENOMEM:printf("内存不足\n");break;caseE2BIG:printf("参数列表太长\n");break;caseENOEXEC:printf("不是可执行文件\n");break;default:perror("exec失败");}exit(1);}intexecl(constchar*path,constchar*arg0,...,(char*)NULL);// 参数以列表形式传递,以NULL结束// 示例:执行 ls -l /tmpexecl("/bin/ls","ls","-l","/tmp",NULL);// 相当于终端命令:$ ls -l /tmpintexecv(constchar*path,char*constargv[]);// 参数以数组形式传递// 示例:执行 ls -l /tmpchar*args[]={"ls","-l","/tmp",NULL};execv("/bin/ls",args);// argv数组必须以NULL结束!intexecle(constchar*path,constchar*arg0,...,(char*)NULL,char*constenvp[]);// 示例:执行程序并传递新环境变量char*env[]={"MYVAR=hello","PATH=/usr/bin",NULL};execle("/bin/sh","sh","-c","echo $MYVAR",NULL,env);intexecve(constchar*path,char*constargv[],char*constenvp[]);// 示例:完全控制参数和环境变量char*args[]={"myprog","-v",NULL};char*env[]={"DEBUG=1","LOG_LEVEL=debug",NULL};execve("/usr/local/bin/myprog",args,env);intexeclp(constchar*file,constchar*arg0,...,(char*)NULL);// 示例:不需要完整路径execlp("ls","ls","-l","/tmp",NULL);// 系统会在PATH中查找ls// 相当于:execl("/bin/ls", "ls", "-l", "/tmp", NULL);intexecvp(constchar*file,char*constargv[]);// 示例:最常用的组合char*args[]={"gcc","test.c","-o","test",NULL};execvp("gcc",args);// 自动在PATH中找gcc#include<unistd.h>#include<sys/wait.h>#include<stdio.h>#include<stdlib.h>intmain(){pid_tpid=fork();if(pid==-1){perror("fork失败");exit(1);}if(pid==0){// 子进程:执行新程序printf("子进程 PID=%d 准备执行新程序\n",getpid());// 方法1:使用execlexecl("/bin/ls","ls","-l","/tmp",NULL);// 方法2:使用execvp// char *args[] = {"ls", "-l", "/tmp", NULL};// execvp("ls", args);// 如果exec失败perror("exec失败");_exit(1);// 子进程结束}else{// 父进程:等待子进程printf("父进程 PID=%d 等待子进程\n",getpid());intstatus;waitpid(pid,&status,0);if(WIFEXITED(status)){printf("子进程退出码: %d\n",WEXITSTATUS(status));}}return0;}