Linux进程控制编程1、fork()函数创建一个新进程(子进程),原进程为父进程,该函数执行一次返回两个值fork 函数使用实例说明
Code:
- #include
- #include
- #include
- #include
-
- int main(void)
- {
- pid_t result;
- result = 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使用实例
Code:
- #include
- #include
- #include
-
- int main()
- {
- char *envp[]={"PATH=/tmp","USER=sunq",NULL};
- char *arg[]={"env",NULL};
-
- if(fork()==0)
- {
-
-
- if(execlp("ps","ps","-ef",NULL)<0)
- perror("execlp error!");
-
-
-
- if(execl("/bin/ps","ps","-ef",NULL)<0)
- perror("execl error!");
-
-
- 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函数的实例
Code:
- #include /* exit 所需头文件 */
- #include /* _exit 所需头文件 */
- #include
-
-
- int main()
- {
-
-
-
-
-
-
- printf("Using _exit .../n");
- printf("This is the content in buffer");
- _exit(0);
- }
-
-
-
-
- printf函数使用的是缓冲I/O方式,该函数在遇到/n时自动将缓冲
- 区的数据读出
-
-
-
-
-
-
-
-
-
-
-
-
一个进程调用了exit 之后,并不马上就完全消失,而是留下僵死进程(Zombie)的数据结构,该进程是非常特殊的进程,它几乎放弃了所有内存空间,没有任何可执行代码,也不能被调度,只是在进程列表中保留一个位置,记载该进程的退出状态等信息供其它进程收集
4、wait 和 waitpid函数
wait 函数是用于使父进程(即调用wait的进程)阻塞,直到一个子进程结束或该进程接到了一个指定的信号
wait 只是 waitpid 的一个特例, waitpid 并不一定要等待第一个终止的子程序,它可提供一个非阻塞版本的wait功能,也能支持作业控制等,在Linux内部实现 wait 函数时直接调用的就是 waitpid 函数
wait 和 waitpid 实例
Code:
- #include
- #include
- #include
- #include
- #include
-
- int main()
- {
- pid_t pc,pr;
- pc=fork();
- if(pc<0)
- {
- printf("Error fork./n");
- exit(1);
- }
- else if(pc==0)
- {
- sleep(5);
- exit(0);
- }
- else
- {
- do
- {
-
-
- pr = wait(NULL);
- if(pr==0)
- {
- 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、创建子进程,父进程退出
Code:
- pid = fork()
- if(pid>0)
- exit(0);
2、在子进程中创建新会话
Code:
- setsid();
3、改变当前目录为根目录
Code:
- chdir("/");
4、重设文件权限掩码
Code:
- umask(0);
5、关闭文件描述符
Code:
- #define MAXFILE 65535
-
- for(i=0;i
- close(i);
守护进程实例:每隔5s在 /tmp/daemon.log 中写入一句话
Code:
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- #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
- 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;
- }