赞
踩
目录
系统数据段又包含(PCB 进程控制块 , pc(程序计数器),堆栈)
PCB:
进程ID
用户名、组名
进程的状态、优先级
文件描述符表(记录打开的文件--用文件描述符标识)
这里先注意一个概念(时间片)
时间片:系统暂时允许(分配)程序运行的时间 看优先级
PC(程序寄存器):
记录程序下一条指令的地址
1)R(run) -- 运行态(就绪态): 正在运行或者准备运行的进程
2)等待态:两种等待态区别在于是否能被信号(对进程的操作指令 例如:kill -9)打断
S(sleep) -- 可中断等待态 :等待某种资源,有资源之后继续执行(相当于原地踏步)
D(deepsleep) -- 不可中断等待态
3)T(time-out) -- 暂停态 :暂停运行,直到有信号唤醒位置
4)Z(zombie) -- 僵尸态 :进程结束之后,没有进行资源回收,该进程状态变为僵尸态
进程优先级取值范围: -20 ~ 19 默认值为零(值越小优先级越高) 默认值为0
nice -n 2 ./a.out 在运行前,将a.out的优先等级设为2
renice -n 2 进程号 //在运行时修改
/a.out+& (后台运行进程)
kill -9 +进程号(杀死后台进程)
bg + 任务号 :将暂停的程序放在后台继续运行
fg + 任务号 :将后台运行的进程换到前台进行
jobs : 查看后台任务
- #include <sys/types.h>//所需头文件
-
- #include <unistd.h>
-
- pid_t fork(void);//函数原型
-
- 返回值:
- 成功创建一个新的子进程
-
- 1)父进程返回子进程的PID号
-
- 2)子进程返回0
-
- 失败父进程返回-1,没有子进程被创建
注:你没有看错这个函数在子进程创建成功时有两个返回值(就看你要接收谁)
举两个栗子:
- #include <stdio.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <stdlib.h>
- int main()
- {
- pid_t pid;
- if ((pid = fork()) = = -1)
- {
- perror("fork");
- return -1;
- }else if (pid = = 0){/*返回值为0代表子进程*/
- printf("The return value is %d In child process!! My PID is %d, My PPID is %d\n",pid,getpid(), getppid());
-
- } else {/*返回值大于0代表父进程*/
- printf("The return value is %d In parent process!! My PID is %d, My PPID is %d\n",pid,getpid(), getppid()); }
- return 0;
-
- }
- #include <stdio.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <stdlib.h>
-
- int main(int argc, char *argv[])
- {
- int a = 2;
- pid_t pid = fork();//接收函数返回值
-
- if(pid < 0)//小于零时则创建失败
- {
- perror("fork");//打印错误原因
- return -1;
- }
- if(pid == 0)//等于零表示创建子程序成功且这个if里面的所有语句是子进程执行
- {
- int n = 10;
- while(n--)
- {
- if(n == 4)
- {
- exit(0);//这个是结束进程函数,之后有讲解
- }
- printf("bbbbbbbbbbbb child_pid = %d a = %d\n", getpid(), a);
- sleep(1);
- }
- }
- else //这里就是>0的情况且代表父进程
- {
- int n = 3;
- while(1)
- {
- printf("aaaaaaaaaaa parent_pid = %d a = %d\n", getpid(), a);
- sleep(1);
- }
- }
-
- return 0;
- }
1)一个进程通过fork函数创建一个新的进程,原本进程称为新进程的父进程,新的进程称为原进
程的子进程子进程会继承父进程中几乎所有数据(包括局部变量、文件标识符) 。
2)如果父进程优先于子进程结束:
子进程称为孤儿进程,由前台进程变为后台进程,统一由init进程(系统默认进程)收养;
3)如果子进程先于父进程结束,且父进程没有回收子进程资源;子进程变成僵尸进程(僵尸态)
一般来说,如果子进程先于父进程结束,子进程应该统一由父进程回收
***子进程在fork语句的下一条指令开始执行
- #include <stdlib.h>//所需头文件
-
- void exit(int status);//函数原型
-
- 参数:
- status :表示进程退出的状态
- 正常结束
- 异常结束 例如:(kill -9)
- #include <unistd.h>
-
- void _exit(int status);
-
- 注意:exit函数调用后会刷新所有缓冲区,_exit函数不会刷新
exit 和 _exit 之间的区别:
eg:
- #include<stdlib.h>
- int main()
- {
- printf("this process will exit!");
-
- exit(0);/*运行到此时停止*/
-
- printf("never be displayed!");
-
- }
- #include <sys/types.h>
- #include <sys/wait.h>
-
- pid_t wait(int *wstatus);
- 参数:
- wstatus:进程结束时,状态信息的首地址
-
- 返回值:
- 成功返回结束子进程的pid号,失败返回-1
-
- 如果想要得到子进程结束的状态信息,可以用以下宏来得到:
-
- WIFEXITED(wstatus) -- 判断一个子进程是否是正常退出,正常退出为真,非正常退出为假
- WEXITSTATUS(wstatus) -- 返回子进程结束的返回值
- WIFSIGNALED(wstatus) -- 判断是否被信号终止
- WTERMSIG(wstatus) -- 打印终止进程信号的编号
-
- 当然还有其他的宏,可以通过man手册查看
- ----------------------------------------------------------------------------------
-
- pid_t waitpid(pid_t pid, int *wstatus, int options);
-
- 参数:
- pid:进程号, -1表示接收任意子进程
- wstatus:进程结束时,状态信息的首地址
- options:
- 0 -- 以阻塞方式等待子进程结束
- WNOHANG -- 以非阻塞方式等待子进程结束
- #include <stdio.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <sys/wait.h>
-
- int main(int argc, char *argv[])
- {
- int a = 2;
- pid_t pid = fork();
-
- if(pid < 0)
- {
- perror("fork");
- return -1;
- }
- if(pid == 0)
- {
- int n = 20;
- while(n--)
- {
- printf("bbbbbbbbbbbb child_pid = %d a = %d\n", getpid(), a);
- sleep(1);
-
- }
- exit(99);
- }
- else
- {
- int ret = -1;
- int status;
- int n = 3;
-
- //pid = wait(&status);
- ret = waitpid(pid, &status, 0);
- if(ret < 0)
- {
- perror("wait");
- exit(-1);
- }
- else
- {
- printf("pid = %d\n", pid);
- }
- printf("%d %d %d %d \n", WIFEXITED(status), WEXITSTATUS(status), WIFSIGNALED(status), WTERMSIG(status));
- }
-
- return 0;
- }
- #include <unistd.h>
-
- l:list列表
- v: argv
- p: PATH环境变量
-
- int execl(const char *pathname, const char *arg, .../* (char *) NULL */);
-
- 参数:
- pathname:执行程序的文件名(包含路径)//默认当前路径
- arg:执行程序的命令行参数,命令行参数列表以NULL结尾
- 返回值:
- 失败返回-1;
- -----------------------------------------------------------------------------
- int execlp(const char *file, const char *arg, .../* (char *) NULL */);
- 参数:
- file:程序名
-
- 添加环境变量:
- 在~/.bashrc中添加命令:
- export PATH=$PATH:你要操作进程的绝对路径
- 配置完成之后,需要用以下指令让配置生效:
- source ~/.bashrc
- --------------------------------------------------------------------------------
-
- //注意以下两个函数,用法都跟上面的函数差不多,只是要注意这里的形参有一个指针数组;
-
- //其实就是把你要操作的进程用一个数组保存,上面的函数只是将这些进程一一列举罢了;
-
- int execv(const char *pathname, char *const argv[]);
-
-
- int execvp(const char *file, char *const argv[]);
-
-
-
-
-
这几组函数加不加P和加P的区别就在于是否默认操作当前路径下的进程,或者是否要改变环境变量
守护进程跟终端无关,负责在后台周期性的处理某些事件或者等待某些事件响应;
1)进程组:
当用户执行一个程序(进程)时,就相当于创建了一个进程组,跟该进程具
有亲缘关系的所有进程都属于该进程组;
2)会话:
当用户打开一个终端时,就创建了一个会话,一个会话由一个或者多个进程
组成,一旦终端关闭,该会话中所有进程组中的进程全部结束;
- 守护进程的创建流程:
-
- 1.创建子进程,父进程退出
-
- fork();
-
- 2.让子进程脱离原本会话
-
- setsid();
-
- setsid函数作用:
- setsid函数用于创建一个新的会话,并使得当前进程成为新会话组的组长
- setsid函数能够使进程完全独立出来,从 而脱离所有其他进程的控制。
-
- 3.修改当前工作路径 -- 非必要
-
- chdir("/tmp");
-
- 4.重设文件权限掩码 -- 非必要
-
- umask(0);
-
- 5.删除进程中所有的文件描述符
-
- getdtablesize()//得到当前
-
- int i = 0;
- for(i = 0; i < ge; i++)
- {
- close(i);
-
- }
-
- while(1)
- {
- //周期性需要执行的事件
-
- }
-
创建一个守护进程,在time.log日志文件中,每隔1s ,记录当前时间
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <strings.h>
- #include <time.h>
- #include <unistd.h>
-
- int main()
-
- {
- fork();//创建子进程
- int pid = fork();
- if (pid > 0) /*父进程退出*/
- {
-
- exit(0);
-
- }
- setsid();//让子进程脱离原本会话
- int i = 0;
- for(i=0; i < getdtablesize();i++)//删除进程中所有的文件描述符
- {
-
- close(i);
-
- }
-
- while(1)//每隔一秒向日志文件写入当前时间
- {
-
- int line = 0;
- time_t t;
- FILE *fp = fopen("time.log", "a+");
- if(NULL == fp)
- {
- perror("fopen");
- return -1;
- }
-
- char buf[64] = {0};
- while( fgets(buf, 64, fp) != NULL)
- {
- if(buf[strlen(buf)-1] == '\n')
- {
- line++;
- }
-
- memset(buf, 0, 64);
- }
-
-
- struct tm * m_t= NULL;
- while(1)
- {
- time(&t);
- m_t = localtime(&t);
-
- fprintf(fp, "%d %d年%d月%d日 %d:%d:%d\n", ++line, m_t->tm_year+1900,m_t->tm_mon+1,m_t->tm_mday,m_t->tm_hour, m_t->tm_min, m_t->tm_sec);
-
- fflush(fp);
- sleep(1);
- }
-
- }
-
- }
注:
1)没有日志文件先在当前目录下创建一个日志文件
2)程序运行后,该守护进程为后台运行,且只能用 kill 结束该进程;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。