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

Linux学习笔记12——Unix中的进程

  通过调用fork和exec函数都能创建新的进程,但两者有着本质的区别:fork函数拷贝了父进程的内存映像,而exec函数用用新的映像来覆盖调用进程的进程映像的功能。

一  fork函数

    #include <unistd.h>

    pid_t fork(void);    //创建子进程成功时,向子进程返回0,并将子进程的进程ID返回给父进程

               //创建失败时,返回-1,并将errno设置为EAGAIN

    返回值是允许父进程和子进程区别自己并执行不同代码的关键特征。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(void){
  pid_t childpid;                     //子进程的ID
  childpid=fork();                    //创建子进程
  if(childpid==-1){                                 //创建子进程失败
    perror("Failed to fork");
    return 1;
  }
  if(childpid==0){                                  //创建子进程成功
    printf("I am child %ld\n",(long)getpid());      //打印子进程的ID
  }
  else{
    printf("I am parent %ld\n",(long)getpid());     //打印父进程的ID
  }   
}

 

二 exec函数

  有六种不同形式的exec函数,如下:

#include <unistd.h>

int execl(const char *path,                      //进程映像文件的路径名,可以是全限定路径名,也可以是相对于当前目录的路径名
      const char *arg,...);               int execle(const char *path,const char *arg,...,char *const envp[]);     //最后一个参数必须以空指针(NULL)作结束 int execlp(const char *file,const char *arg,...); int execv(const char *path,
      char *const argv[]);        //参数数组,用来存放指向你的字符串参数的指针数组 int execve(const char *path,char *const argv[],char *const envp[]); int execvp(const char *file,char *const argv[]);

  execv开头的函数是把参数以"char *argv[]"这样的形式传递命令行参数。而execl开头的函数采用了我们更容易习惯的方式,把参数一个一个列出来,然后以一个NULL

表示结束,也可以写成(char *)0。

  如果创建子进程不成功,所有的exec函数都返回-1,并设置errno,以下是errno的类型和原因。

  E2BIG:新进程的参数表和环境表长度以系统所允许的ARG_MAX字节的限制要长

  EACCES:对新进程路径前缀中目录的搜寻权限被否定,新进程映像文件的执行权限被否定,或者新进程映像文件不是正常的文件,且不能被执行

  EINVAL:新进程映像文件有恰当的权限,且以可识别可执行的二进制格式出现

  ELOOP:在对参数path或file进行解析时存在循环

  ENAMETOOLONG:path或file的长度超出了PATH_MAX的范围,或者路径名组件比NAME_MAX要长

  ENOENT:path或file组件命名的不是一个现存的文件,或者path或file为空字符串

  ENOEXEC:映像文件有恰当的访问权限,但它的格式不可识别(不适用于execlp或execvp)

  ENOTDIR:映像文件路径前缀的组件不是一个目录

     int main(int argc,char *argv[],char *envp[])
        {
             char *arg[]={"ls","-a",NULL};
             if(fork()==0)
             {
                 printf("execl...........\n");
                 if(execl("/bin/ls","ls","-a",NULL)<0)
                 {
                      fprintf(stderr,"execl failed:%s",strerror(errno));
                      return -1;
                 }
             }
             if(fork()==0)
             {
                 printf("execv...........\n");
                 if(execv("/bin/ls",arg)<0)
                 {
                     fprintf(stderr,"execl failed:%s\n",strerror(errno));
                     return -1;
                 }
             }
             if(fork()==0)
             {
                 printf("execlp...........\n");
                 if(execlp("ls","ls","-a",NULL)<0)
                 {
                     fprintf(stderr,"execl failed:%s",strerror(errno));
                     return -1;
                 }
             }
             if(fork()==0)
             {
                 printf("execvp...........\n");
                 if(execvp("ls",arg)<0)
                 {
                     fprintf(stderr,"execl failed:%s\n",strerror(errno));
                     return -1;
                 }
             }
             if(fork()==0)
             {
                 printf("execle...........\n");
                 if(execle("/bin/ls","ls","-a",NULL,envp)<0)
                 {
                     fprintf(stderr,"execl failed:%s",strerror(errno));
                     return -1;
                 }
             }
             if(fork()==0)
             {
                 printf("execve...........\n");
                 if(execve("/bin/ls",arg,envp)<0)
                 {
                     fprintf(stderr,"execl failed:%s\n",strerror(errno));
                     return -1;
                 }
             }

          return 0;
        }

 

 

转载于:https://www.cnblogs.com/zjzsky/p/3481254.html

相关文章:

  • C#访问lua获取一个全局基本数据类型——table映射成C#中interface
  • C#访问lua获取全局函数——映射成delegate
  • C#访问lua获取一个table中的函数——映射成interface中的函数
  • C#访问lua获取全局函数——此函数带多个返回值
  • [置顶] sqlserver2008 新建表之后无法更改表设计的原因
  • lua访问C#中类——访问成员+方法
  • C++中dynamic_cast
  • 数据结构-反转链表
  • lua中rawget和rawset
  • Linux红黑树(二)——访问节点
  • lua中继承
  • SPOJ REPEATS Repeats (后缀数组:子串的最大循环节)题解
  • lua在什么时候设置元表失败呢
  • lua中通过__index继承父类的属性
  • C++中匿名函数的捕获列表和匿名函数的说明
  • android 一些 utils
  • Android优雅地处理按钮重复点击
  • Elasticsearch 参考指南(升级前重新索引)
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • Mybatis初体验
  • React 快速上手 - 07 前端路由 react-router
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • REST架构的思考
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • windows下使用nginx调试简介
  • 不上全站https的网站你们就等着被恶心死吧
  • 从零开始在ubuntu上搭建node开发环境
  • 京东美团研发面经
  • 强力优化Rancher k8s中国区的使用体验
  • 延迟脚本的方式
  • 怎么将电脑中的声音录制成WAV格式
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • (c语言版)滑动窗口 给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度
  • (libusb) usb口自动刷新
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • .cn根服务器被攻击之后
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .Net8 Blazor 尝鲜
  • [ 蓝桥杯Web真题 ]-布局切换
  • [Android] Implementation vs API dependency
  • [Angular] 笔记 7:模块
  • [BZOJ] 3262: 陌上花开
  • [ccc3.0][数字钥匙] UWB配置和使用(二)
  • [codevs 2822] 爱在心中 【tarjan 算法】
  • [Linux] - 定时任务crontab
  • [Linux内存管理-分页机制]—把一个虚拟地址转换为物理地址
  • [oeasy]python0004_游乐场_和python一起玩耍_python解释器_数学运算
  • [scikit-learn] 第一章 初识scikit-learn及内置数据集介绍
  • [SHELL]shell scripts笔记(1)
  • [TS] Class Properties Public, Private and Read Only Modifiers
  • [UnityEditor基础]脚本自动定位选择Hierarchy或Project下的对象
  • [VSCode] Shortcuts
  • [WeChall] PHP 0815 (Exploit, PHP) Write Up