linux进程控制
2015-06-01 01:41
274 查看
linux 进程控制 1
首先,linux是一个多任务多进程的操作系统,所以必须要讨论进程的控制。
进程:
进程是一个动态的实体,是程序的一次执行过程,它是操作系统的资源分配的基本单位,简单来说线程和进程区别不大,一个主要的区别就是进程有自己的内存空间,并且占用系统资源。
进程标识:进程的一个重要的标识就是其进程的ID ,PID。
一般使用如下的一些函数来获取ID ,
getpid( ) 获得进程的PID
getppid( ) 获得父进程的PID
getuid( ) 获得实际用户ID
geteuid( ) 获得有效ID
getgid( ) 获得实际的组ID
getegid( ) 获得有效的组ID
进程的状态:
运行状态:正在运行或者等待运行
可中断等待状态:进程正在等待某个事件完成,等待过程就可以被信号或者定时器唤醒
不可中断等待状态:同上但是不能被唤醒,只有在等待的时间完成后,才可以继续进行
僵死状态:进程已经终止,但描述符还存在,直到父进程调用WAIT( )函数释放‘
停止状态:进程因为受到了指示结束或暂停的信号,停止运行。
进程的一些状态标示:
< :高优先级
N :低优先级
L :内存页面不可换出
S :首进程
I :多线程进程
+ : 进程为于前台进程组
进程的控制函数:
fork; 用于创建一个进程
exit: 用于终止进程
exec: 用于执行一个应用程序
wait: 将父进程挂起,等待子进程终止
getpid:获取当前进程的ID
nice: 更改进程的优先级
创建一个进程:
创建一个进程的方式一般有两种:
1。由操作系统创建
2. 由父进程创建
fork( ) 函数是创建一个新进程的唯一方法(init进程是由内核创建)
此函数一般有两个返回值:
1.一个返回值为0,这是子进程fork( )返回的值,为0,标示成功创建
2.另一个值为PID ,表示子进程的ID 。
这个程序就是使用fock 函数创建一个进程然后返回父进程的ID 和子进程的ID。
一般来说,创建进程之后是父进程先执行还是子进程先执行是不确定的,这个顺序取决于当下使用系统的调度算法。
子进程一般会继承父进程的很多属性:
用户ID,组ID,当前工作目录,根目录,打开的文件,创建文件时使用的屏蔽字,信号屏蔽字,上下文环境,共享的存储段,资源限制等。
同时他们二者还有不同的属性:
进程有它自己的唯一的进程ID。
fork( )的返回值不同,父进程返回子进程的ID ,子进程返回0
每一个子进程的ID 只能是创建他的父进程所给的ID 。
子进程共享父进程的打开的文件描述符,但父进程对文件描述符的改变不会影响子进程中的文件描述符。
子进程不继承父进程的设置的文件锁
子进程不继承父进程的警告
子进程的未决信号集被清空
孤儿进程:
当一个父进程死亡后,他的子进程就变成了孤儿进程,且被init进程收养
vfork( ) 函数与 fork( )函数的比较
1。都是创建一次返回两次,因为前者实际上是调用了后者
2。后者完全复制父进程的资源与地址等,有良好的并发性,后者是共享地址空间与资源
3。前者保证首先运行子进程,当使用了exec,exit 时父进程才会被调用,如果在这些调用之前需要使用父进程就会导致死锁。
死锁:
所谓死锁: 是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
发生死锁有4个产生条件;
1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
守护进程:
守护进程就是在后台运行的进程,他不占用终端,一般用来执行固定的一些任务。
创建一个守护进程的步骤:
(1)在父进程中执行fork并exit推出;
(2)在子进程中调用setsid函数创建新的会话;
(3)在子进程中调用chdir函数,让根目录 ”/” 成为子进程的工作目录;
(4)在子进程中调用umask函数,设置进程的umask为0;
(5)在子进程中关闭任何不需要的文件描述符
#include<stdio.h>
#include<sys/types.h>
这个程序用来创建一个守护进程,然后这个进程每隔一秒就删除
这两个文件(这是不停生成的日志文件,同理用守护进程不同的生成这两个文件)
进程退出正常退出方法有两种,异常退出方法有三种:
1.正常退出
return退出
调用exit( ) 函数退出
调用_exit( )函数退出
2.异常退出
调用abort( )函数退出
进程收到某个信号自动退出
各种退出方式的比较:
exit( ) , return:前者时函数,接受参数,返回后将控制权限交给系统
后者返回将控制权限交给,调用函数
exit( ) , abort( ): 前者是正常退出,后者是异常退出
exit(exit_code): 参数为0代表正常退出,参数不为0,代表有错误发生
exit( ) ,_exit( ): 两者不再同一个头文件里,后者执行后立即返回给内核,前者需要执行一系列的清除操作,然后将控制权交给内核。
执行新的进程:
#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,
..., 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[]);
这是exec一族的全部函数。
execv:此函数通过调用路径名的方式调用可执行文件作为新的进程映像,后面的参数就是命令行参数
execve:此系统调用参数是路径名,后便的参数和main( )函数是对应的
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
wait( )函数就是等待进程结束他的接受值用来存放进程的退出码。
改变进程的优先级,
#include <unistd.h>
int nice(int inc);
他的参数就指定的优先级的数值;
一个示例程序,其中getproiority 是获得当下进程优先级的函数.
首先,linux是一个多任务多进程的操作系统,所以必须要讨论进程的控制。
进程:
进程是一个动态的实体,是程序的一次执行过程,它是操作系统的资源分配的基本单位,简单来说线程和进程区别不大,一个主要的区别就是进程有自己的内存空间,并且占用系统资源。
进程标识:进程的一个重要的标识就是其进程的ID ,PID。
一般使用如下的一些函数来获取ID ,
getpid( ) 获得进程的PID
getppid( ) 获得父进程的PID
getuid( ) 获得实际用户ID
geteuid( ) 获得有效ID
getgid( ) 获得实际的组ID
getegid( ) 获得有效的组ID
进程的状态:
运行状态:正在运行或者等待运行
可中断等待状态:进程正在等待某个事件完成,等待过程就可以被信号或者定时器唤醒
不可中断等待状态:同上但是不能被唤醒,只有在等待的时间完成后,才可以继续进行
僵死状态:进程已经终止,但描述符还存在,直到父进程调用WAIT( )函数释放‘
停止状态:进程因为受到了指示结束或暂停的信号,停止运行。
进程的一些状态标示:
< :高优先级
N :低优先级
L :内存页面不可换出
S :首进程
I :多线程进程
+ : 进程为于前台进程组
进程的控制函数:
fork; 用于创建一个进程
exit: 用于终止进程
exec: 用于执行一个应用程序
wait: 将父进程挂起,等待子进程终止
getpid:获取当前进程的ID
nice: 更改进程的优先级
创建一个进程:
创建一个进程的方式一般有两种:
1。由操作系统创建
2. 由父进程创建
fork( ) 函数是创建一个新进程的唯一方法(init进程是由内核创建)
此函数一般有两个返回值:
1.一个返回值为0,这是子进程fork( )返回的值,为0,标示成功创建
2.另一个值为PID ,表示子进程的ID 。
#include<stdio.h> #include<sys/types.h> #include<unistd.h> #include<stdlib.h> int main() { pid_t pid; printf("Process Creation Study\n"); pid = fork(); switch(pid) { case 0: printf("child process is runing ,curpid is %d,parentpid is %d\n",pid,getppid()); break; case -1: printf("process creat failed\n"); break; default: printf("parent process is runing ,childpid is %d,parentpid is %d\n",pid,getpid()); break; } exit(0); }
这个程序就是使用fock 函数创建一个进程然后返回父进程的ID 和子进程的ID。
一般来说,创建进程之后是父进程先执行还是子进程先执行是不确定的,这个顺序取决于当下使用系统的调度算法。
子进程一般会继承父进程的很多属性:
用户ID,组ID,当前工作目录,根目录,打开的文件,创建文件时使用的屏蔽字,信号屏蔽字,上下文环境,共享的存储段,资源限制等。
同时他们二者还有不同的属性:
进程有它自己的唯一的进程ID。
fork( )的返回值不同,父进程返回子进程的ID ,子进程返回0
每一个子进程的ID 只能是创建他的父进程所给的ID 。
子进程共享父进程的打开的文件描述符,但父进程对文件描述符的改变不会影响子进程中的文件描述符。
子进程不继承父进程的设置的文件锁
子进程不继承父进程的警告
子进程的未决信号集被清空
孤儿进程:
当一个父进程死亡后,他的子进程就变成了孤儿进程,且被init进程收养
vfork( ) 函数与 fork( )函数的比较
1。都是创建一次返回两次,因为前者实际上是调用了后者
2。后者完全复制父进程的资源与地址等,有良好的并发性,后者是共享地址空间与资源
3。前者保证首先运行子进程,当使用了exec,exit 时父进程才会被调用,如果在这些调用之前需要使用父进程就会导致死锁。
死锁:
所谓死锁: 是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
发生死锁有4个产生条件;
1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
守护进程:
守护进程就是在后台运行的进程,他不占用终端,一般用来执行固定的一些任务。
创建一个守护进程的步骤:
(1)在父进程中执行fork并exit推出;
(2)在子进程中调用setsid函数创建新的会话;
(3)在子进程中调用chdir函数,让根目录 ”/” 成为子进程的工作目录;
(4)在子进程中调用umask函数,设置进程的umask为0;
(5)在子进程中关闭任何不需要的文件描述符
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h> #include<unistd.h> #include<stdlib.h> #include<fcntl.h> #include<signal.h> #include<sys/param.h> int creat_daemon(void) { int pid; int i; signal(SIGTTOU,SIG_IGN); //忽略IO信号 signal(SIGTTIN,SIG_IGN); signal(SIGTSTP,SIG_IGN); signal(SIGHUP,SIG_IGN); pid = fork(); if(pid > 0){ exit(0); //结束父进程 }else if(pid < 0){ printf("fork error :%d\n",__LINE__); return -1; } //建立一个新的进程组,在这个新的进程组中,子进程成为这个进程组的首进程,以使该进程脱离所有的终端 setsid(); //再次创建一个子进程,保证该进程不是进程组的首进程,同时让它无法打开一个新的终端 pid = fork(); if(pid > 0){ exit(0); }else if(pid < 0){ return -1; } for(i = 0;i < NOFILE;close(i++));//关闭所有从父进程那里继承来的不再需要的文件描述符 //chdir("/");改变工作目录 umask(0); //将文件屏蔽字设为0 signal(SIGCHLD,SIG_IGN); //忽略SIGCHLD 信号 return 0; } int main() { time_t now; creat_daemon(); while(1){ sleep(1); remove("daemon.log"); remove("daemon_create.log"); } return 0; }
这个程序用来创建一个守护进程,然后这个进程每隔一秒就删除
daemon.log<pre name="code" class="cpp" style="color: rgb(51, 51, 51); line-height: 24px; text-indent: 36px;">daemon_create.log
这两个文件(这是不停生成的日志文件,同理用守护进程不同的生成这两个文件)
进程退出正常退出方法有两种,异常退出方法有三种:
1.正常退出
return退出
调用exit( ) 函数退出
调用_exit( )函数退出
2.异常退出
调用abort( )函数退出
进程收到某个信号自动退出
各种退出方式的比较:
exit( ) , return:前者时函数,接受参数,返回后将控制权限交给系统
后者返回将控制权限交给,调用函数
exit( ) , abort( ): 前者是正常退出,后者是异常退出
exit(exit_code): 参数为0代表正常退出,参数不为0,代表有错误发生
exit( ) ,_exit( ): 两者不再同一个头文件里,后者执行后立即返回给内核,前者需要执行一系列的清除操作,然后将控制权交给内核。
执行新的进程:
#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,
..., 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[]);
这是exec一族的全部函数。
execv:此函数通过调用路径名的方式调用可执行文件作为新的进程映像,后面的参数就是命令行参数
execve:此系统调用参数是路径名,后便的参数和main( )函数是对应的
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
wait( )函数就是等待进程结束他的接受值用来存放进程的退出码。
改变进程的优先级,
#include <unistd.h>
int nice(int inc);
他的参数就指定的优先级的数值;
#include<stdio.h> #include<sys/types.h> #include<unistd.h> #include<sys/resource.h> #include<sys/wait.h> #include<stdlib.h> int main() { pid_t pid; int stat_val ; //标识进程返回符 int oldpri,newpri; //标识新旧优先级 printf("nice study\n"); pid = fork(); //创建一个进程 switch(pid){ case 0: printf("child is runing ,curpid is %d,parentpid is %d\n",pid,getppid()); //成功创建展示进程的ID oldpri = getpriority(PRIO_PROCESS,0); //获得子进程的原始优先级 printf("old priority = %d\n",oldpri); //打印子进程的原始优先级 newpri = nice(2); //将新优先级设置为2 printf("New priority = %d\n",newpri); //打印新的优先级 exit(0); case -1: perror("process creation failed\n"); break ; default: printf("parent is runing ,childpid is %d,Parent is %d\n",pid,getpid()); break ; } wait(&stat_val); exit(0); }
一个示例程序,其中getproiority 是获得当下进程优先级的函数.
相关文章推荐
- Linux安装SmartSVN及破解
- centos7配置环境
- linux下arm驱动开发环境配置
- linux命令总结
- Linux的文件类型和权限操作
- Linux下c程序的编译方法:
- Linux分区机制和常见命令
- Linux下jdk的安装和配置
- CentOS7的yum安装mysql
- linux基础
- CentOS配置静态IP
- Linux内核(2.6)进程调度算法
- 【linux系统优化】CentOS中yum更新源的配置及使用
- 【linux系统优化】CentOS中yum更新源的配置及使用
- linux内部指令知识点小节
- LINUX-用户和用户组管理
- 玩转Linux之必修内功(基础篇)
- Linux高级编程(一)
- Linux高级编程(二)
- Linux高级编程(三)