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

网站的栏目和板块浙江建设厅网站 打不开

网站的栏目和板块,浙江建设厅网站 打不开,it程序员工资一般多少,博客可以放自己做的网站此为牛客Linux C和黑马Linux系统编程课程笔记。 1. fork函数 1.1 fork创建单个子进程 #includeunistd.h pid_t fork(void);作用#xff1a;创建一个子进程。 pid_t类型表示进程ID#xff0c;但为了表示-1#xff0c;它是有符号整型。(0不是有效进程ID#xff0…此为牛客Linux C和黑马Linux系统编程课程笔记。 1. fork函数 1.1 fork创建单个子进程 #includeunistd.h pid_t fork(void);作用创建一个子进程。 pid_t类型表示进程ID但为了表示-1它是有符号整型。(0不是有效进程IDinit最小为1)返回值失败返回-1成功返回① 父进程返回子进程的ID(非负) ②子进程返回 0 注意返回值不是fork函数能返回两个值而是fork后fork函数变为两个父子需【各自】返回一个。创建失败主要有以下两个原因 当前系统的进程数已经达到了系统规定的上限这时 errno 的值被设置为 EAGAIN系统内存不足这时 errno 的值被设置为 ENOMEM 我们常常利用fork()的返回值来判断当前在父进程还是在子进程中。 示例程序 #include unistd.h #include stdio.hint main() {pid_t pid fork();if(pid 0) {// 父进程printf(This is parent process, pid is %d\n, getpid());} else if(pid 0) {// 子进程printf(This is child process, pid is %d, my parents pid is %d\n, getpid(), getppid());}return 0; }运行结果为 1.2 循环创建多个子进程 如果现在想要使用fork()编写一个能够创建多个子进程的程序该如何编写直观的想法是直接循环 #include unistd.h #include stdio.hint main() {int i;for(i 0; i 3; i) {pid_t pid fork();}printf(im a process, my pid is %d\n, getpid());return 0; }执行发现输出了8个语句说明一共有8个进程。 这是因为fork出的子进程也在执行当前程序也就是说当前趟循环创建出的子进程在也会执行下一次循环的fork()创建出子进程的子进程最后一共创建了1247个子进程故一共有8个进程。 要想只创建当前父进程的3个子进程需要如此编写 #include unistd.h #include stdio.hint main() {int i;for(i 0; i 3; i) {pid_t pid fork();if(pid 0) {break;}}printf(im a process, my pid is %d, my ppid is %d\n, getpid(), getppid());return 0; }再执行发现输出了4个语句 其中前三个都是父进程22000的子进程。 1.3 fork父子进程的虚拟内存空间 父子进程之间在fork后。有哪些相同那些相异之处呢 刚fork之后 父子相同处: 全局变量、.data、.text、栈、堆、环境变量、用户ID、宿主目录、进程工作目录、信号处理方式… 父子不同处: 1.进程ID 2.fork返回值 3.父进程ID 4.进程运行时间 5.闹钟(定时器) 6.未决信号集 似乎子进程复制了父进程0-3G用户空间内容以及父进程的PCB但pid不同。真的每fork一个子进程都要将父进程的0-3G地址空间完全拷贝一份然后在映射至物理内存吗 当然不是!父子进程间遵循读时共享写时复制的原则。这样设计无论子进程执行父进程的逻辑还是执行自己的逻辑都能节省内存开销。 以全局变量为例一旦父进程或子进程要对一全局变量做修改其对应的子进程或父进程就把该全局变量复制一份到自己的虚拟内存空间中映射至新的物理内存看如下示例代码 #include unistd.h #include stdio.hint var 1;int main() {int i;pid_t pid fork();if(pid 0) {var 2;printf(parent var %d\n, var);}else if(pid 0) {var 3;printf(child var %d\n, var);}return 0; }执行结果为 可见全局变量是读时共享写时复制。 【重点】父子进程共享1. 文件描述符(打开文件的结构体) 2. mmap建立的映射区 (进程间通信详解) 特别的fork之后父进程先执行还是子进程先执行不确定。取决于内核所使用的调度算法。 2. exec函数族 2.1 介绍 exec 函数族的作用是根据指定的文件名找到可执行文件并用它来取代调用进程的内容换句话说就是在调用进程内部执行一个可执行文件。 fork创建子进程后执行的是和父进程相同的程序但有可能执行不同的代码分支子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时该进程的用户空间代码和数据完全被新程序替换从新程序的启动例程开始执行。调用exec并不创建新进程所以调用exec前后该进程的pid并未改变。 exec 函数族的函数执行成功后不会返回因为调用进程的实体包括代码段数据段和堆栈等都已经被新的内容取代只留下进程 ID 等一些表面上的信息仍保持原样颇有些神似“三十六计”中的“金蝉脱壳”。看上去还是旧的躯壳却已经注入了新的灵魂。只有调用失败了它们才会返回 -1从原程序的调用点接着往下执行如图 左边是某进程的虚拟地址空间及内容该进程内部使用exec执行了a.out可执行文件右边红色的是a.out文件虚拟地址空间中的用户区则调用结束以后该进程如图 替换原进程用户区内容内核区不变。 exec函数族如下 int execl(const char *path, const char *arg, ...)/* (char *) NULL */); int execlp(const char *file, const char *arg, ...) /* (char *) NULL */); int execle(const char *path, const char *arg, ...)/*, (char *) NULL, char * const envp[] */); int execv(const char *path, char *const argv[]); int execvp(const char *file, char *const argv[]); int execvpe(const char *file, char *const argv[], char *const envp[]); int execve(const char *filename, char *const argv[], char *const envp[]);前六个函数是标准C库函数最后一个是linux系统函数。前六个函数是调用最后一个函数实现的。 各个函数名都已exec开头后面为以下字母组合分别代表不同功能 l(list) 参数地址列表以空指针结尾v(vector) 存有各参数地址的指针数组的地址p(path) 按 PATH 环境变量指定的目录搜索可执行文件e(environment) 存有环境变量字符串地址的指针数组的地址 最常用函数为execl函数。 2.2 execl int execl(const char *path, const char *arg, ...)参数 path:需要指定的执行的文件的路径或者名称推荐使用绝对路径。 arg:是执行可执行文件所需要的参数列表需要注意 第一个参数一般没有什么作用为了方便一般写的是执行的程序的名称 从第二个参数开始往后就是程序执行所需要的的参数列表。 参数最后需要以NULL结束哨兵 返回值只有当调用失败才会有返回值返回-1并且设置errno如果调用成功没有返回值。 示例程序 主程序execl.c: #include unistd.h #include stdio.hint var 1;int main() {pid_t pid fork();if(pid 0) {printf(im parent, pid is %d\n, getpid());sleep(1);}else if(pid 0) {execl(child, child, NULL);printf(its execl.c program\n);}return 0; }调用的子程序child.c #include unistd.h #include stdio.hint main() {printf(im child, pid is %d, ppid is %d\n, getpid(), getppid());return 0; }执行主程序结果如下 印证了之前的说法子进程调用execl执行child程序后进程号不变。 而主程序中的printf(its execl.c program\n);没有被执行说明子进程调用execl后程序段已经被替换。 3. wait和waitpid函数 学习wait函数之前我们最好先要了解什么是孤儿进程什么是僵尸进程。 3.1 孤儿进程 看下面的示例程序 #include unistd.h #include stdio.hint main() {pid_t pid fork();if(pid 0) {printf(im parent, pid is %d\n, getpid());}else if(pid 0) {sleep(1);printf(im child, my parent pid is %d\n, getppid());}return 0; }fork出子进程后让子进程睡眠1秒后再执行printf语句此时父进程已经运行结束该子进程便成了孤儿进程运行结果如下 一秒后输出 可以看到子进程的父进程的pid为1在linux中正是init进程对应的进程号可见当出现孤儿进程时init进程会”收养“该进程。 3.2 僵尸进程 如果父进程调用了wait( )或者waitpid( )父进程将会释放已经执行完的子进程的PCB资源如果父进程没有调用了wait( )或者waitpid( )父进程结束后init进程收养了子进程后init进程也将负责释放子进程的PCB资源但是如果父进程是一个循环或者一直在执行那父进程结束之前它的已经执行完的子进程就成为了僵尸进程。 看如下示例程序 #include unistd.h #include stdio.hint main() {pid_t pid fork();if(pid 0) {while(1) {printf(im parent, pid is %d\n, getpid());sleep(1);}} else if(pid 0) {printf(im child, pid is %d\n, getpid());}return 0; }父进程循环子进程变成了僵尸进程使用ps -aux查看进程状态可以看到子进程的状态为Z意思时僵尸进程。 接下来继续介绍wait和waitpid函数。 3.3 wait函数 #include sys/types.h #include sys/wait.h pid_t wait(int *wstatus);功能等待当前进程的任意一个子进程结束如果任意一个子进程结束了此函数会回收该子进程的资源。 参数int *wstatus 为进程退出时的状态信息传入的是一个int指针类型的变量传出参数。 返回值 成功返回被回收的子进程的id 失败-1 (代表所有的子进程都是结束的调用函数失败) 调用wait函数的进程会被挂起阻塞直到它的一个子进程退出或者收到一个不能被忽略的信号时才被唤醒相当于继续往下执行 如果没有子进程了函数立刻返回返回-1如果子进程都已经结束了也会立即返回返回-1. 示例程序如下 #include sys/types.h #include sys/wait.h #include unistd.h #include stdio.hint main() {pid_t pid fork();if(pid 0) {int ret wait(NULL);if(ret -1) {printf(no child);} else {printf(child %d is dead, ret);}sleep(1);} else if(pid 0) {while(1) {printf(im child, pid is %d\n, getpid());sleep(1);}}return 0; }程序运行后子进程无限循环父进程由于调用了wait函数在等待子进程退出而处于阻塞态现在我们使用kill -9 杀死子进程后输出如下 可见子进程结束后父进程从wait处开始继续执行并且返回了子进程的pid。 3.4 waitpid函数 与wait相近只不过能够指定回收的进程pid。 #include sys/types.h #include sys/wait.h pid_t waitpid(pid_t pid, int *wstatus, int options);功能回收指定进程号的子进程可以设置是否阻塞。 参数 pid: pid 0 : 某个子进程的pidpid 0 : 回收当前进程组的所有子进程pid -1 : 回收任意子进程相当于 wait()pid -1 : 某个进程组的组id的绝对值回收指定进程组中的子进程 options设置阻塞或者非阻塞 0 : 阻塞WNOHANG : 非阻塞 返回值 0 返回子进程的id0 : optionsWNOHANG, 且子进程正在运行。-1 错误或者没有子进程了 注意一次wait或waitpid调用只能清理一个子进程清理多个子进程应使用循环。
http://www.pierceye.com/news/705788/

相关文章:

  • 成都网站定制中心知名的中文域名网站有哪些
  • 福州长乐网站建设网站流量统计分析
  • 四川网站建设公司 登录六盘水市诚信网站建设公司
  • 优秀包装设计网站软件工程师工作
  • 舟山建设信息港网站泉州百度网络推广
  • 网站流量宝镜像别人网站做排名的好处
  • 如何学习网站建设app网络营销方案设计题
  • 高端品牌网站建设明细报价报腾讯云 win wordpress
  • 云南建设网站网站建设公司现在还挣钱吗
  • 濮阳微信网站建设没有数据库的网站
  • 网站开发与没计是做什么贵阳查房子备案的网站
  • 做网站学不需要做后台管理系统mean网站开发
  • 网页网站公司如何做备份游戏型网站开发
  • 网站排名必做阶段性seo策略软文写作是什么意思
  • 网站域名商渭南哪家公司可以做网站
  • 医院网站asp源码加强机关网站建设
  • wordpress建手机站网站建设规划大纲
  • 同个主体新增网站备案施工企业副总经理竞聘
  • 视频网站后台设计针式个人知识库管理系统
  • 外围网站开发网页制作对联
  • 深圳福永网站建设网站多个用户怎样建设
  • 百度网站排名怎么提高wordpress页面全屏的插件
  • 企业网站优化方式wordpress 外链播放器
  • 设计衣服的网站久久诗歌网
  • 上海网站营销it运维网
  • 一起做网店广州站怎么推广软件让别人下载
  • 王晴儿网站建设方案wordpress媒体库 ftp
  • 乡村建设网站自己的网站做防伪码
  • 企业网站托管新乡企业网站建设
  • 移动网站开发课程设计莱芜四中网站