首页 / C语言 / C语言基础-进程相关
C语言基础-进程相关
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C语言基础-进程相关,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5773字,纯文字阅读大概需要9分钟。
内容图文
![C语言基础-进程相关](/upload/InfoBanner/zyjiaocheng/939/689614551327458082764710572bc137.jpg)
进程的概念
程序
- 存放在磁盘上的 指令和数据的有序集合(文件)
- 静态的
进程
- 执行一个程序所分配的资源总称
- 进程是程序一次执行过程
- 动态的,包括创建、调度、执行和消亡
进程控制块(pcd)
- 进程标识PID
- 进程用户
- 进程状态、优先级
- 文件描述符表
进程类型
- 交互进程:在shell下启动。以在前台运行,也可以在后台运行
- 批处理进程:和终端无关,被提交到一个作业队列中,以便顺序执行
- 守护进程:和终端无关一直在后台运行
进程状态
- 运行态:
- 正在运行
- 准备运行
- 等待态:进程在等待一个事件的发生或某种资源
- 可终端
- 不可中断
- 停止态:进程被中止,收到信号后可继续运行
- 死亡态:以终止的进程,但pcb没有被释放
查看进程信息
- ps 查看系统进程快照
- top 查看进程动态信息
- /proc 查看进程详细信息
修改进程优先级
- nice 按用户指定的优先级运行进程
- nice -n num ./test
- num范围是 -20~19 越低优先级越高
- 普通用户是没办法指定负数的优先级
- renice 改变正在运行进程的优先级
- renice -n num pid
- 普通用户是没办法提高该优先级,只能进行降低
进程相关
- jobs 查看后台进程
- bg 将挂起的进程在后台运行
- bg id
- id是jobs的后台进程编号
- fg 吧后台运行的程序放到前台来运行
- fg id
- id 是jobs的后台进程编号
- ctrl + z 将前台进程放到后台挂起
C与进程相关函数
父子进程
- 子进程继承了父进程的内容
- 父子进程有独立的地址空间,互不影响
- 若父进程先结束
- 子进程成为孤儿进程,被init进程收养
- 子进程变成后台进程
- 若子进程先结束
- 父进程如果没有及时回收,子进程变成僵尸进程
进程创建 - fork
#include <unistd.h> pid_t fork(void); // 创建新的进程,失败返回-1 // 成功时父进程返回子进程的进程号,子进程返回0
创建完子进程后,从fork后下一条语句开始执行;
父子进程的执行顺序不定
父子进程可以多次调用fork
获取当前进程 - getpid
#include <unistd.h> pid_t getpid(void);
demo:创建子进程
#include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) { pid_t pid; if ((pid = fork()) < 0) { perror("fork"); return -1; } else if (pid == 0) { printf("child process: my pid is :%d\n",getpid()); }else{ printf("parent process :%d\n",getpid()); } } /* 输出: parent process :7124 child process: my pid is :7125 */
结束进程
#include <stdlib.h> void exit(int status); #include <unistd.h> void _exit(intstatus); // 引入的头文件不同 //*** exit结束进程时会刷新(流)的缓冲区 // _exit结束时不会刷新缓冲区 可能会造成流文件丢失
exit(0) // 退出当前程序
进程资源回收
- 子进程结束时由父进程回收
- 孤儿进程由init进程回收
- 若没有及时回收会出现僵尸进程
#include <unistd.h> pid_t wait(int *status); // status指定保存子进程返回值和结束方式的地址 // status为NULL表示直接释放子进程PCB,不接受返回值 // 成功时返回回收的子进程号 // 失败是返回EOF // 若子进程没有结束,父进程会一直阻塞 // 若有多个子进程,那个先结束就先回收
Demo:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> int main(int argc, char *argv[]) { pid_t pid; int status = 0; if ((pid = fork()) < 0) { perror("fork"); return -1; } else if (pid == 0) { printf("child process: my pid is :%d\n", getpid()); sleep(1); exit(2); } else { wait(&status); printf("%x\n", status); printf("parent process :%d\n", getpid()); } }
进程回收的另一种方式
#include <unistd.h> pid_t waitpid(pid_t pid,int * status,int option); // pid可用于指定回收那个子进程或任意子进程 // pid= -1 代表当前进程的任意子进程 // status指定用于保存子进程返回值和结束方式的地址 // option指定回收方式,0或WNOHANG // 0表示阻塞一直等到进程结束 // WNOHANG表示非阻塞 // 成功时返回子进程的pid或0 0表示当前子进程还未结束 // 失败时返回EOF
进程返回值和结束方式
- 子进程通过exit、_exit/return返回某个值(0~255)
- 父进程调用wait(&status)回收
WIFEXITED(status) // 判断子进程是否正常结束 0为false 1为true
WEXITSTATUS(status) // 获取子进程返回值
WIFSIGNALED(status) // 判断子进程是否被信号结束
WTERMSIG(status) // 获取结束子进程的信号类型
守护进程
- 守护进程(Deamon)是linux三种进程类型之一
- 通常是在系统启动时运行,系统关闭时结束
- linux系统中大量使用,很多服务程序以守护进程方式运行
会话、控制终端
- linux会话(session)、进程组的方式管理进程
- 每个进程属于一个进程组
- 会话是一个或多个进程组的集合。通常用户打开一个终端,系统会创建一个会话。所有通过该终端运行的进程都属于这个会话
- 终端关闭时,所有相关进程会被结束
守护进程特点
- 始终在后台运行
- 独立于任何终端
- 周期性的执行某种任务或等待处理特定事件
守护进程创建
- 创建子进程,父进程退出--子进程变为孤儿进程,被init进程收养;子进程在后台运行(还是会依附于当前终端)
if (fork() > 0) { exit(0); }
- 子进程创建新会话--子进程称为新的会话组长;脱离原先的终端
- 更改当前工作目录--守护进程一直在后台运行,其工作目录不能被卸载一般指向根目录(/)或(tmp)
chdir("/"); // 普通用户指向这个目录可读 chdir("/tmp"); // 所有用户都是最高权限
- 重设文件权限掩码--文件权限掩码设置为0;只影响当前进程
#include <sys/stat.h> if (umask(0) < 0) { exit(-1); }
- 关闭父进程打开的文件描述符--已脱离终端 stdin/stdout/stderr 无法再使用
#include <zconf.h> for (int i = 0; i < getdtablesize(); ++i) { close(i); }
Demo:每隔1秒写入时间到time.log
exec函数族
- 进程调用exec函数族执行某个程序
- 进程当前内容被指定的程序替换
- 实现让父子进程执行不同程序
- 父进程创建 子进程
- 子进程调用exec函数族
- 父进程不受影响
通过shell命令去执行其他程序
#include <unistd.h> int execl(const char *path,const char*arg,...); / int execlp(const char *file,const char *arg,...); // 成功执行指定的程序 // 失败返回EOF // path找到要执行程序的名称(要包含路径) // arg...传递给执行程序的参数表 // file 执行程序的名称,在$PATH中查找
Demo:
if (execl("/bin/ls", "ls", "-a","/etc") < 0) { perror("excel"); }
if (execlp("ls", "ls", "-a","/etc") < 0) { perror("excel"); }
通过shell命令去执行其他程序 参数为数组
#include <unistd.h> int execv(const char * path,char * const argv[]); int execvp(const char * file,char * const argv[]); // 成功时执行指定的成 // 失败返回EOF // arg... 封装成指针数组 比上面exec更加灵活
char *arg[] = {"ls", "-a", "/etc",NULL}; if (execv("/bin/ls", arg) < 0) { perror("excel"); }
char *arg[] = {"ls", "-a", "/etc",NULL}; if (execvp("ls", arg) < 0) { perror("excel"); }
通过shell命令去执行其他程序 字符串
#include <stdlib.h> int system(const char * command); // 会自动创建一个子进程去执行command // 成功返回command指令的返回值 // 失败返回EOF
<style></style>
内容总结
以上是互联网集市为您收集整理的C语言基础-进程相关全部内容,希望文章能够帮你解决C语言基础-进程相关所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。