嵌入式Linux学习《四》 进程控制
来源:互联网 发布:java nio reactor 编辑:程序博客网 时间:2024/05/17 07:33
Linux进程控制编程
1、fork()函数创建一个新进程(子进程),原进程为父进程,该函数执行一次返回两个值
fork 函数使用实例说明
- #include <sys/types.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- int main(void)
- {
- pid_t result;
- result = fork(); //调用fork函数
- if(result == -1) //进行出错处理
- {
- perror("fork");
- exit;
- }
- else if(result == 0)
- {
- printf("The return value is %d/nIn child process!!/nMy PID is %d/n",result,getpid());
- }
- else
- {
- printf("The return value is %d/nIn father process!!/nMy PID is %d/n",result,getpid());
- }
- }
由于fork完整地拷贝了父进程的整个地址空间,执行速度是比较慢的,为了加快fork的执行速度,有了vfork的产生,vfork也能创建新进程,但不产生父进程的副本,只是允许父子进程访问相同的物理内存,只有当子进程需要改变内存中数据时才拷贝父进程,这是著名的 “写操作时拷贝” 技术 (copy-on-write)
2、exec函数族
fork函数用于创建一个子进程,exec函数族提供了一个在进程中启动另一个程序执行方法
exec函数族成员语法
函数名的最后一个字符:l ( list ) 代表逐个列举的方式,v ( vector ) 表示将所有参数整体构造指针数组传递,e (Environment) 指定当前进程所使用的环境变量,以上设置时候参数必须以NULL表示结束
exec使用实例
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- int main()
- {
- char *envp[]={"PATH=/tmp","USER=sunq",NULL};
- char *arg[]={"env",NULL};
- if(fork()==0)
- {
- /* 调用 execlp函数,这里相当于调用了 ps -ef 命令 */
- if(execlp("ps","ps","-ef",NULL)<0)
- perror("execlp error!");
- /* 调用 execl函数,需要绝对路径 */
- if(execl("/bin/ps","ps","-ef",NULL)<0)
- perror("execl error!");
- /* 调用 execle 函数 */
- if(execle("/bin/env","env",NULL,envp)
- perror("execle error!");
- if(execve("/bin/env",arg,envp)<0)
- perror("execve error!");
- }
- }
exec函数族使用一定要加上错误判断语句,因为exec很容易执行失败,其中原因常见有
(1)、找不到文件或路径,此时errno被设备为 ENOENT
(2)、数据 argv 和 envp 忘记用 NULL结束,此时errno 被设置为 EFAULT
(3)、没有对应的可执行文件的运行权限,此时 errno 被设置为 EACCES
事实上,6个函数中真正的系统调用只有 execve,其它5个都是库函数,最终都会调用 execve 这个系统调用
3、exit 和 _exit函数
exit 和 _exit函数都是用来终止进程,当程序执行到 exit 或 _exit时,会无条件停止剩下的所有操作,清除包括PCB在内的各种数据结构,并终止本进程的进行,exit 函数在退出前会将缓冲区的内容写入到文件中,要想保证数据的完整性,就一定要使用exit函数
exit和_exit函数的实例
- #include <stdlib.h> /* exit 所需头文件 */
- #include <unistd.h> /* _exit 所需头文件 */
- #include <stdio.h>
- int main()
- {
- /* ============================================
- printf("Using exit .../n");
- printf("This is the content in buffer");
- exit(0);
- ==============================================*/
- printf("Using _exit .../n");
- printf("This is the content in buffer");
- _exit(0);
- }
- /* ====================================================
- printf函数使用的是缓冲I/O方式,该函数在遇到/n时自动将缓冲
- 区的数据读出
- exit 输出结果:
- Using exit ...
- This is the content in buffer
- _exit 输出结果:
- Uisng _exit ...
- 由此可知,调用 _exit函数无法输出缓冲区中的记录
- ==================================================== */
一个进程调用了exit 之后,并不马上就完全消失,而是留下僵死进程(Zombie)的数据结构,该进程是非常特殊的进程,它几乎放弃了所有内存空间,没有任何可执行代码,也不能被调度,只是在进程列表中保留一个位置,记载该进程的退出状态等信息供其它进程收集
4、wait 和 waitpid函数
wait 函数是用于使父进程(即调用wait的进程)阻塞,直到一个子进程结束或该进程接到了一个指定的信号
wait 只是 waitpid 的一个特例, waitpid 并不一定要等待第一个终止的子程序,它可提供一个非阻塞版本的wait功能,也能支持作业控制等,在Linux内部实现 wait 函数时直接调用的就是 waitpid 函数
wait 和 waitpid 实例
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- int main()
- {
- pid_t pc,pr; /* <sys/types.h> typedef pid_t short */
- pc=fork();
- if(pc<0)
- {
- printf("Error fork./n");
- exit(1);
- }
- else if(pc==0)
- {
- sleep(5);
- exit(0);
- }
- else
- {
- do /* 循环测试子进程是否退出 */
- {
- /* pr = waitpid(pc,NULL,WNOHANG); */
- /* pr = waitpid(pc,NULL,0); */
- pr = wait(NULL);
- if(pr==0) /* 若子进程未退出,则父进程暂停1s */
- {
- printf("The child process is Not exit!/n");
- sleep(1);
- }
- }while(pr==0);
- if(pr==pc) /* 若子进程退出,则打印相应情况 */
- printf("Get Child PID %d/n",pr);
- else
- printf("Some error occurs/n");
- }
- return 0;
- }
5、Linux守护进程的创建
按照5个步骤:
1、创建子进程,父进程退出
- pid = fork()
- if(pid>0)
- exit(0);
2、在子进程中创建新会话
- setsid();
3、改变当前目录为根目录
- chdir("/");
4、重设文件权限掩码
- umask(0);
5、关闭文件描述符
- #define MAXFILE 65535
- for(i=0;i<MAXFILE;i++)
- close(i);
守护进程实例:每隔5s在 /tmp/daemon.log 中写入一句话
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <sys/wait.h>
- #define MAX 65535
- int main()
- {
- pid_t pc;
- int len,i,fd;
- char *buf = "This is a daemon/n";
- len = strlen(buf);
- pc=fork();
- if(pc<0)
- {
- printf("error fork!/n");
- exit(1);
- }
- else if(pc>0)
- exit(0);
- setsid();
- chdir("/");
- umask(0);
- for(i=0;i<MAX;i++)
- close(i);
- while(1)
- {
- if((fd=open("/tmp/message",O_CREAT|O_WRONLY|O_APPEND,0600))<0)
- {
- perror("open");
- exit(1);
- }
- write(fd,buf,len+1);
- close(fd);
- sleep(5);
- }
- return 0;
- }
- 嵌入式Linux学习《四》 进程控制
- Linux 学习笔记(四)进程控制
- 嵌入式Linux学习笔记第四天 ——进程控制
- 【嵌入式学习历程13】Linux进程控制编程
- Linux进程学习四
- Linux进程学习四
- Linux嵌入式 -- 内核 - 进程控制 和 调度
- 嵌入式学习笔记_Linux(三)——Linux进程控制
- 嵌入式学习笔记_Linux(四)——Linux进程通信
- Linux进程控制基础(四)
- linux学习之进程控制
- linux学习 进程控制编程
- linux进程学习笔记一--进程控制
- Linux进程线程学习笔记:进程控制
- 进程控制理论<四>---那些年我们一起学习linux程序设计 .
- 嵌入式Linux进程与信号(学习笔记)
- 嵌入式 Linux环境进程间通信(四):信号灯
- 学习linuxC编程实战-----linux进程控制
- 设定电脑自动关机
- 梦比路长
- DOS简介
- dos文件的分类
- 开发自己的进程管理器(C#)
- 嵌入式Linux学习《四》 进程控制
- jsp中MVC模式——网络交友(一)
- 程序员的45个习惯
- java几个概念
- Java 泛型编程小记
- 学习电脑的心得
- 值传递 和址传递
- junit的来源
- csdn