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

做网站 徐州网站建设维护费一年多少钱

做网站 徐州,网站建设维护费一年多少钱,网页qq登陆聊天,怎样做网站挣钱🌟 各位看官好,我是maomi_9526! 🌍 种一棵树最好是十年前,其次是现在! 🚀 今天来学习C语言的相关知识。 👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更…

🌟 各位看官好,我是maomi_9526

🌍 种一棵树最好是十年前,其次是现在!

🚀 今天来学习C语言的相关知识。

👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更多人哦

目录

1. 进程程序替换

2.exec函数

2.1 execl 

2.2 execlp 

2.3 execle 

2.4 execv 

2.5 execvp 

2.6 execvpe 

 2.7execve

2.8命名理解

3.进程替换

3.1进程替换原理

4. 自主Shell命令行解释器

4.1获取当前环境信息

4.2输出命令行提示符

4.3获取命令行输入

4.4执行命令行

4.4.1执行内建命令 

4.4.2执行外部命令

4.5更新环境变量

3. Shell 实现完整代码


1. 进程程序替换

  • fork() 系统调用创建一个子进程,父子进程开始执行相同的程序代码。若子进程要执行一个不同的程序,可以使用 exec 系列函数来实现程序的替换。

  • 这些 exec 函数会加载一个全新的程序(包括代码和数据)到子进程的地址空间中,并从新程序的入口点开始执行,原有的程序代码被替换掉。exec 函数系列中最常用的是 execve,其他的 execl, execlp, execv, execvp, execle 等只是 execve 的不同封装。

2.exec函数

头文件:#include<unistd.h>

返回值:当失败时返回-1

2.1 execl 

int execl(const char *path, const char *arg, ...);

execl("/usr/bin/ls","ls","-l",NULL);
2.2 execlp 

int execlp(const char *file, const char *arg, ...);

execlp("ls","ls","-l",NULL);
2.3 execle 

int execle(const char *path, const char *arg, ..., char * const envp[]);

extern char**environ;//声明全局环境变量
execle("/usr/bin/ls","1s","-l","-a",NULL,environ};
2.4 execv 

int execv(const char *path, char *const argv[]);

char*argv[]={"1s","-l","-a",NULL};execv("/usr/bin/ls",argv);
2.5 execvp 

int execvp(const char *file, char *const argv[]);

char*argv[]={"1s","-l","-a",NULL};execvp("ls",argv);
2.6 execvpe 

int execvpe(const char *file, char *const argv[],char *const envp[]);


char*argv[]={"ls","-a","-l",NULL};
execvpe("ls",argv,environ);
     2.7execve

    系统调用函数execve

    上面的exec系列函数本质上都不是系统级别的调用,都是对execve的语言级别的封装

    int execve(const char *filename, char *const argv[], char *const envp[]);

     

    2.8命名理解
    • l(list) : 表示参数采用列表
    • v(vector) : 参数用数组
    • p(path) : 有p自动搜索环境变量PATH
    • e(env) : 表示自己维护环境变量
    函数级别函数名列表传参是否带路径是否使用当前环境变量
    语言级别execl列表
    execlp列表
    execle列表
    execv数组
    execvp数组
    execvpe数组
    系统级别execve数组

    3.进程替换

    3.1进程替换原理

    当进程执行了代码替换操作后,原先加载的代码会被新的代码所替换。

    此时,原有的代码不再存在于进程的地址空间中,执行流转向新的代码。具体来说,在进程替换时,原代码的内存空间被新的代码段覆盖,新的代码开始运行。此过程的本质是将进程的代码区域替换为新的内容,从而导致原有代码失效并不可再访问。

    所以原来代码我的进程执行完毕并不会出现。 

    4. 自主Shell命令行解释器

    • 通过实现一个自定义的 shell,可以处理命令行输入,并根据输入执行对应的命令。Shell 需要有以下功能:

    4.1获取当前环境信息

    getenv() 是一个 C 标准库函数,用于从环境变量中获取指定名称的值。环境变量是系统级的变量,它们存储了操作系统和程序运行时需要的配置信息,比如系统路径、用户设置等。getenv() 函数通过读取这些环境变量,允许程序动态地获取环境设置。

    头文件:#include<stdlib.h>

    函数:char *getenv(const char *name);

    返回值:

    • 成功:如果找到了指定名称的环境变量,getenv() 会返回该变量的值(一个指向字符数组的指针,代表该环境变量的值)。

    • 失败:如果未找到指定的环境变量,getenv() 返回 NULL

    代码实现:

    //获取当前环境信息
    const char* GETPWD()
    {char *pwd=getenv("PWD");return pwd==NULL?"None":pwd;
    }//获取用户信息
    const char*GETUSER()
    {char*user=getenv("USER");return user==NULL?"None":user;
    }//获取系统信息
    const char*GETHOSTNAME()
    {char*hostname=getenv("HOSTNAME");return hostname==NULL?"None":hostname;
    }
    
    4.2输出命令行提示符

    snprintf 是 C 语言标准库中的一个函数,属于 stdio.h 头文件。它的作用是将格式化的数据输出到一个字符数组中,并且保证不会发生缓冲区溢出。snprintf 函数是对 sprintf 的一种改进,主要是增加了一个最大字符数的限制,避免了 sprintf 在没有足够空间时造成内存溢出的风险。 

    头文件:#include<stdio.h>

    int snprintf(char *str, size_t size, const char *format, ...);

    返回值:

    • 成功:返回写入字节数(当被写入内容超过写入大小,发生截断)

    • 失败:返回负数 

    #define COMMAND_SIZE 1024
    #define FORMAT "[%s@%s %s]#"
    void MakeCMDPrompt(char cmdprompt[],size_t size)//制作命令行提示符
    {snprintf(cmdprompt,size,FORMAT,GETUSER(),GETHOSTNAME(),GETPWD());
    }
    void PrintCMDPrompt()//打印命令行提示符
    {char prompt[COMMAND_SIZE];MakeCMDPrompt(prompt,sizeof(prompt));printf("%s",prompt);
    }
    
    4.3获取命令行输入

    fgets 是 C 语言标准库中的一个函数,属于 stdio.h 头文件。它的作用是从指定的文件流中读取一行字符串,并将读取的内容存储到一个字符数组中。与 gets 不同,fgets 可以避免缓冲区溢出的问题,因为它会限制读取的字符数。 

    头文件:#include<stdio.h>

    char *fgets(char *s, int size, FILE *stream);

    返回值:

    • 成功 :返回写入的s的位置
    • 失败:返回NULL

     代码实现:

    //接受命令行
    bool MakeCMDLine(char*out,size_t size)
    {char*line=fgets(out,size,stdin);if(line==NULL) return false;//返回值为空,写入失败out[strlen(out)-1]=0;//去除输入的换行符if(strlen(out)==0) return false;return true;
    }

    4.2解析命令行

    将用户输入的命令解析成可执行的命令和参数。

    strtok 是 C 语言标准库中的一个函数,属于 string.h 头文件。它用于将一个字符串分割成一系列子字符串(tokens),根据指定的分隔符。该函数通常用于处理由空格、逗号、换行符等字符分隔的文本数据。

    char *strtok(char *str, const char *delim);

    • str:待分割的字符串。如果是第一次调用 strtok,该参数应为需要分割的字符串;如果是后续调用,应该传递 NULL,以继续分割上一次传入的字符串。

    • delim:分隔符字符串,定义了用于分割字符串的字符集合。可以是单个字符,也可以是多个字符,strtok 会将字符串中的任何一个分隔符都视为分隔点。

    //分割字符串
    bool CMDLinePrase(char *line)
    {
    #define ADC " "g_argc=0;//每次初始化为0,确保每个命令都是从首位开始g_argv[g_argc++]=strtok(line,ADC);while(g_argv[g_argc++]=strtok(nullptr,ADC));g_argc--;return true;
    }
    
    4.4执行命令行
    4.4.1执行内建命令 

    通过父进程本身来进行执行:(cd命令)

    头文件:#include<unistd.h>

     int chdir(const char *path);

    bool CheckBuiltIn()
    {std::string cmd=g_argv[0];if(cmd=="cd"){if(g_argc==1){chdir(GETHOME());return true;}else{std::string pwd=g_argv[1];chdir(pwd.c_str());}return true;}return false;
    }
    
    4.4.2执行外部命令

     通过子进程来进行执行:

    //子程序进行进程替换执行命令
    int Execute()
    {int id=fork();if(id==0){//chileexecvp(g_argv[0],g_argv);exit(1);}//fatherint idd=waitpid(id,NULL,0);//阻塞等待(void)idd;//使用避免报错return 0;
    }
    
    4.5更新环境变量

    getcwdunistd.h 头文件中的一个函数,用于获取当前工作目录。 

     #include<unistd.h>

    char *getcwd(char *buf, size_t size);

    • buf:一个字符数组的指针,用来存储获取的当前工作目录的路径。你需要在调用 getcwd 之前分配足够的内存空间来存储路径。

    • sizebuf 指针指向的字符数组的大小。它指定了 buf 能够存储的最大字符数。

    char g_env[1024];
    char g_cwd[1024];void ChangEnv()
    {const char*cwd=getcwd(g_cwd,sizeof(g_cwd));if(cwd!=nullptr){snprintf(g_env,sizeof(g_env),"PWD=%s",g_cwd);putenv(g_env);}
    }
    

    3. Shell 实现完整代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cstdlib>
    #include<unistd.h>
    #include<sys/types.h>
    #include<sys/wait.h>
    #define COMMAND_SIZE 1024
    #define FORMAT "[%s@%s %s]#"
    #define MAXARGC 128
    char g_env[1024];
    char g_cwd[1024];
    char* g_argv[MAXARGC];
    int g_argc=0;
    const char* GETPWD()
    {char *pwd=getenv("PWD");return pwd==NULL?"None":pwd;
    }
    const char*GETUSER()
    {char*user=getenv("USER");return user==NULL?"None":user;
    }
    const char*GETHOSTNAME()
    {char*hostname=getenv("HOSTNAME");return hostname==NULL?"None":hostname;
    }
    const char*GETHOME()
    {char*home=getenv("HOME");return home==NULL?"None":home;
    }
    void ChangEnv()
    {const char*cwd=getcwd(g_cwd,sizeof(g_cwd));if(cwd!=nullptr){snprintf(g_env,sizeof(g_env),"PWD=%s",g_cwd);putenv(g_env);}
    }
    bool CheckBuiltIn()
    {std::string cmd=g_argv[0];if(cmd=="cd"){if(g_argc==1){chdir(GETHOME());return true;}else{std::string pwd=g_argv[1];chdir(pwd.c_str());}ChangEnv();return true;}return false;
    }
    std::string DirName(const char* pwd)
    {
    #define SLASH "/"std::string dir=pwd;auto pose=dir.rfind(SLASH);if(pose==std::string::npos) return "BUG?";return dir.substr(pose+1);
    }
    void MakeCMDPrompt(char cmdprompt[],size_t size)
    {//snprintf(cmdprompt,size,FORMAT,GETUSER(),GETHOSTNAME(),GETPWD());snprintf(cmdprompt,size,FORMAT,GETUSER(),GETHOSTNAME(),DirName(GETPWD()).c_str());
    }
    void PrintCMDPrompt()
    {char prompt[COMMAND_SIZE];MakeCMDPrompt(prompt,sizeof(prompt));printf("%s",prompt);
    }
    bool MakeCMDLine(char*out,size_t size)
    {char*line=fgets(out,size,stdin);if(line==NULL) return false;out[strlen(out)-1]=0;if(strlen(out)==0) return false;return true;
    }
    bool CMDLinePrase(char *line)
    {
    #define ADC " "g_argc=0;g_argv[g_argc++]=strtok(line,ADC);while(g_argv[g_argc++]=strtok(nullptr,ADC));g_argc--;return g_argc==0?false:true;
    }
    void PrintCMDLinePrase()
    {for(int i=0;g_argv[i];i++){printf("argv[%d]->%s\n",i,g_argv[i]);}printf("argc :%d\n",g_argc);
    }
    void Print()
    {char cmdline[COMMAND_SIZE];if( MakeCMDLine(cmdline,sizeof(cmdline))){printf("%s",cmdline);}
    }
    int Execute()
    {int id=fork();if(id==0){//chileexecvp(g_argv[0],g_argv);exit(1);}//fatherint idd=waitpid(id,NULL,0);//阻塞等待(void)idd;//使用避免报错return 0;
    }
    int main()
    {while(true){PrintCMDPrompt();char cmdline[COMMAND_SIZE];if(! MakeCMDLine(cmdline,sizeof(cmdline))){continue;}if(!CMDLinePrase(cmdline)){continue;}if(CheckBuiltIn()){continue;}Execute();}return 0;
    }
    

    文章转载自:

    http://KvH1ze5Q.bmgnz.cn
    http://j8dhuKih.bmgnz.cn
    http://77xXyyJE.bmgnz.cn
    http://m5AeObX9.bmgnz.cn
    http://r49fU0pu.bmgnz.cn
    http://AcOG1x8g.bmgnz.cn
    http://lRb08WCw.bmgnz.cn
    http://y95LzGk3.bmgnz.cn
    http://9MUK76do.bmgnz.cn
    http://PVZXSNye.bmgnz.cn
    http://2DzYGY02.bmgnz.cn
    http://hwSUC9Tw.bmgnz.cn
    http://VCtFThD0.bmgnz.cn
    http://wG8pMvv3.bmgnz.cn
    http://EzCMPqdA.bmgnz.cn
    http://ltn58htj.bmgnz.cn
    http://rS7mYBdF.bmgnz.cn
    http://sCnLw5kg.bmgnz.cn
    http://guxzUsij.bmgnz.cn
    http://D3ieKtSw.bmgnz.cn
    http://eBOMc7HA.bmgnz.cn
    http://z3Wcp8uw.bmgnz.cn
    http://x2fjuajG.bmgnz.cn
    http://eYGNrSug.bmgnz.cn
    http://ktatFWXZ.bmgnz.cn
    http://2AZyfQff.bmgnz.cn
    http://uJfFnZCH.bmgnz.cn
    http://cXizy9VU.bmgnz.cn
    http://AIWzI3tc.bmgnz.cn
    http://bp0Sjbtu.bmgnz.cn
    http://www.dtcms.com/wzjs/739229.html

    相关文章:

  • 网站的分类有哪些类型微信对接网站
  • 谷歌云做网站服务器网站后台无法编辑文字
  • 合肥做公司网站公司陕西网站建设品牌公司推荐
  • 怎么用手机做网站平台做云词图的网站
  • 小橘子被做h网站wordpress只允许vip可以推广
  • 如何使用记事本做网站网站等保测评
  • 成都营销网站制作关于单位网站建设的报告
  • 苏州网站建设运营推广大数据
  • 做哪些网站比较赚钱方法有哪些谷歌浏览器网址
  • 网站制作网免费策划公司职位
  • 北京上云科技网站建设什么是网站收录
  • 承德网站建设wordpress更换域名后台登不进去
  • 个人博客网站建设预算陕西做网站公司有哪些
  • 企业网站如何建设报告滁州做网站的公司
  • 没有备案的网站能否帮网上支付福州云建站
  • 高端网站建设开发制作网站语言
  • 移动端响应式网站怎么做个人网站seo
  • 做问卷的网站网站标题权重吗
  • 牟平建设企业网站天津商业网站建设
  • 西安技术网站建设免费设计logo图标生成器
  • 如何利用NAS做网站wordpress 图片论坛
  • 请写出网站建设前期需要做的准备阿里邮箱注册
  • php英文网站源码门户网站是不是新媒体
  • 网站认证打款怎么做分录制作网页教程
  • 平顶山建设局网站zencart中文网站
  • 厦门网站建设培训费用WordPress碎语
  • 在百度上做网站多少钱网络规划与设计思维导图
  • 登录手机网站模板htmlwordpress 插件交互
  • 石龙网站设计效果好的网站建
  • 那个网站可以做域名跳转的开办网络公司