嵌入式Linux学习《四》 进程控制

来源:互联网 发布:java nio reactor 编辑:程序博客网 时间:2024/05/17 07:33

Linux进程控制编程

1、fork()函数创建一个新进程(子进程),原进程为父进程,该函数执行一次返回两个值

fork 函数使用实例说明

Code:
  1. #include <sys/types.h>   
  2. #include <unistd.h>   
  3. #include <stdio.h>   
  4. #include <stdlib.h>   
  5.   
  6. int main(void)   
  7. {   
  8.     pid_t result;   
  9.     result = fork();          //调用fork函数   
  10.     if(result == -1)          //进行出错处理   
  11.     {   
  12.         perror("fork");   
  13.         exit;   
  14.     }   
  15.     else if(result == 0)   
  16.     {   
  17.         printf("The return value is %d/nIn child process!!/nMy PID is %d/n",result,getpid());   
  18.     }   
  19.     else  
  20.     {   
  21.         printf("The return value is %d/nIn father process!!/nMy PID is %d/n",result,getpid());   
  22.     }   
  23. }  

由于fork完整地拷贝了父进程的整个地址空间,执行速度是比较慢的,为了加快fork的执行速度,有了vfork的产生,vfork也能创建新进程,但不产生父进程的副本,只是允许父子进程访问相同的物理内存,只有当子进程需要改变内存中数据时才拷贝父进程,这是著名的 “写操作时拷贝” 技术 (copy-on-write)

2、exec函数族

fork函数用于创建一个子进程,exec函数族提供了一个在进程中启动另一个程序执行方法

exec函数族成员语法

函数名的最后一个字符:l  ( list ) 代表逐个列举的方式,v ( vector ) 表示将所有参数整体构造指针数组传递,e (Environment) 指定当前进程所使用的环境变量,以上设置时候参数必须以NULL表示结束

exec使用实例

Code:
  1. #include <unistd.h>   
  2. #include <stdio.h>   
  3. #include <stdlib.h>   
  4.   
  5. int main()   
  6. {   
  7.     char *envp[]={"PATH=/tmp","USER=sunq",NULL};   
  8.     char *arg[]={"env",NULL};   
  9.   
  10.     if(fork()==0)    
  11.     {   
  12.         /* 调用 execlp函数,这里相当于调用了 ps -ef 命令 */  
  13.   
  14.         if(execlp("ps","ps","-ef",NULL)<0)   
  15.             perror("execlp error!");   
  16.   
  17.         /* 调用 execl函数,需要绝对路径 */  
  18.   
  19.         if(execl("/bin/ps","ps","-ef",NULL)<0)   
  20.             perror("execl error!");   
  21.   
  22.         /* 调用 execle 函数 */  
  23.         if(execle("/bin/env","env",NULL,envp)   
  24.             perror("execle error!");   
  25.   
  26.         if(execve("/bin/env",arg,envp)<0)   
  27.             perror("execve error!");   
  28.     }   
  29.   
  30. }  

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函数的实例

Code:
  1. #include <stdlib.h>            /* exit  所需头文件  */   
  2. #include <unistd.h>            /* _exit 所需头文件  */   
  3. #include <stdio.h>   
  4.   
  5.   
  6. int main()   
  7. {   
  8.   /* ============================================   
  9.     printf("Using exit .../n");  
  10.     printf("This is the content in buffer");  
  11.     exit(0);   
  12.   ==============================================*/        
  13.        
  14.     printf("Using _exit .../n");   
  15.     printf("This is the content in buffer");   
  16.     _exit(0);   
  17. }   
  18.   
  19.   
  20. /* ====================================================   
  21.    
  22.     printf函数使用的是缓冲I/O方式,该函数在遇到/n时自动将缓冲
  23.     区的数据读出
  24.  
  25.     exit 输出结果:  
  26.    
  27.     Using exit ...  
  28.     This is the content in buffer  
  29.       
  30.     _exit 输出结果:  
  31.       
  32.     Uisng _exit ...  
  33.       
  34.     由此可知,调用 _exit函数无法输出缓冲区中的记录  
  35.    ==================================================== */  

一个进程调用了exit 之后,并不马上就完全消失,而是留下僵死进程(Zombie)的数据结构,该进程是非常特殊的进程,它几乎放弃了所有内存空间,没有任何可执行代码,也不能被调度,只是在进程列表中保留一个位置,记载该进程的退出状态等信息供其它进程收集

4、wait 和 waitpid函数

wait 函数是用于使父进程(即调用wait的进程)阻塞,直到一个子进程结束或该进程接到了一个指定的信号 
wait 只是 waitpid 的一个特例, waitpid 并不一定要等待第一个终止的子程序,它可提供一个非阻塞版本的wait功能,也能支持作业控制等,在Linux内部实现 wait 函数时直接调用的就是 waitpid 函数


wait 和 waitpid 实例

Code:
  1. #include <sys/types.h>   
  2. #include <sys/wait.h>   
  3. #include <unistd.h>   
  4. #include <stdio.h>   
  5. #include <stdlib.h>   
  6.     
  7. int main()   
  8. {   
  9.         pid_t pc,pr;    /* <sys/types.h> typedef pid_t short */  
  10.         pc=fork();   
  11.         if(pc<0)   
  12.         {   
  13.                 printf("Error fork./n");   
  14.                 exit(1);   
  15.         }   
  16.         else if(pc==0)   
  17.         {   
  18.                 sleep(5);   
  19.                 exit(0);   
  20.         }   
  21.         else  
  22.         {   
  23.                 do      /* 循环测试子进程是否退出 */  
  24.                 {   
  25.                         /* pr = waitpid(pc,NULL,WNOHANG); */  
  26.                         /* pr = waitpid(pc,NULL,0); */  
  27.                         pr = wait(NULL);   
  28.                         if(pr==0)             /* 若子进程未退出,则父进程暂停1s */  
  29.                         {   
  30.                                 printf("The child process is Not exit!/n");   
  31.                                 sleep(1);        
  32.                         }   
  33.                 }while(pr==0);   
  34.                 if(pr==pc)        /* 若子进程退出,则打印相应情况 */  
  35.                         printf("Get Child PID %d/n",pr);   
  36.                 else  
  37.                         printf("Some error occurs/n");   
  38.         }   
  39.         return 0;   
  40. }  


5、Linux守护进程的创建

按照5个步骤:

1、创建子进程,父进程退出

Code:
  1. pid = fork()   
  2.         if(pid>0)   
  3.                 exit(0);  

2、在子进程中创建新会话

Code:
  1. setsid();  

3、改变当前目录为根目录

Code:
  1. chdir("/");  

4、重设文件权限掩码

Code:
  1. umask(0);  

5、关闭文件描述符

Code:
  1. #define MAXFILE 65535   
  2.   
  3. for(i=0;i<MAXFILE;i++)   
  4.         close(i);  

守护进程实例:每隔5s在 /tmp/daemon.log 中写入一句话

Code:
  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. #include <string.h>   
  4. #include <fcntl.h>   
  5. #include <sys/types.h>   
  6. #include <unistd.h>   
  7. #include <sys/wait.h>   
  8.     
  9. #define MAX 65535   
  10.     
  11. int main()   
  12. {   
  13.         pid_t pc;   
  14.         int len,i,fd;   
  15.         char *buf = "This is a daemon/n";   
  16.         len = strlen(buf);   
  17.         pc=fork();   
  18.         if(pc<0)   
  19.         {   
  20.                 printf("error fork!/n");   
  21.                 exit(1);   
  22.         }   
  23.         else if(pc>0)   
  24.                 exit(0);   
  25.         setsid();   
  26.         chdir("/");   
  27.         umask(0);   
  28.         for(i=0;i<MAX;i++)   
  29.                 close(i);   
  30.         while(1)   
  31.         {   
  32.                 if((fd=open("/tmp/message",O_CREAT|O_WRONLY|O_APPEND,0600))<0)   
  33.                 {   
  34.                         perror("open");   
  35.                         exit(1);   
  36.                 }   
  37.                 write(fd,buf,len+1);   
  38.                 close(fd);   
  39.                 sleep(5);   
  40.         }   
  41.         return 0;   
  42. }   

 

原创粉丝点击