linux入门教程超详细交流学习,linux基础你掌握了几个
linux入门教程超详细交流学习,linux基础你掌握了几个#include <stdio.h> #include <unistd.h> #include <stdlib.h> int main(void){ pid_t pid; //创建子进程 pid=fork(); if(pid==-1){ perror("fork"); return 1; } if(pid==0){//子进程的代码 sleep(5); printf("child...\n"); //getchar(); exit(0); }else{//父进程的代码 printf("parent...\n"); exit(0); } return 0; } 执行结果wait 回收进程资源#include
进程的退出returen 和 exit,return 只是函数的返回,而 exit 却是进程的结束。void exit(int status);
#include <stdlib.h>
void exit(int status);
功能:终止进程
参数:
status:退出状态码。status&0377的值给父进程。
返回值:
永远不返回。
代码示例
- test.c
#include <stdio.h>
#include <stdlib.h>
int main(void){
getchar();
exit(-1);
}
注册进程结束调用函数
在进程结束前,可以注册一些函数给进程,在进程结束时会自动调用这些被注册的函数。
on_exit(3)
#include <stdlib.h>
int on_exit(void (*function)(int void *) void *arg);
功能:注册一个函数给进程,在进程终止的时候调用该函数
参数:
function:指定退出函数的名字
void (*function)(int void *)
arg:指定退出函数的第二个参数
返回值:
0 成功
非0 错误
代码示例(on_exit)
- on_exit.c
#include <stdio.h>
#include <stdlib.h>
void doit(int n void *arg){
printf("n=%d\targ:%s\n" \
n (char *)arg);
return;
}
int main(void){
//向进程注册退出函数
on_exit(doit "beijing");
getchar();
exit(3);
}
atexit(3)
#include <stdlib.h>
int atexit(void (*function)(void));
功能:注册一个函数给进程,在进程终止的时候调用该函数
参数:
function:指定了要注册的函数的名字
返回值:
0 成功
非0 错误
代码示例(atexit)
- atexit.c
#include <stdio.h>
#include <stdlib.h>
//注册给进程的退出函数
void doit(void){
printf("hahha....\n");
return;
}
int main(void){
//向进程注册一个退出处理函数
atexit(doit);
getchar();
return 0;
}
在进程退出后,父进程会回收子进程的资源。
使用 wait(2)、waitpid(2) 系统调用回收子进程的资源。
如果父进程早于子进程结束,那么父进程的子进程的父亲就改变成为 init 进程,这种进程被成为孤儿进程。
- lonely.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void){
pid_t pid;
//创建子进程
pid=fork();
if(pid==-1){
perror("fork");
return 1;
}
if(pid==0){//子进程的代码
sleep(5);
printf("child...\n");
//getchar();
exit(0);
}else{//父进程的代码
printf("parent...\n");
exit(0);
}
return 0;
}
- 执行结果
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
功能:等待进程改变状态。
参数:
status:退出状态码的地址。子进程的退出状态存放在这块地址空间里。可以使用一些宏检测退出原因。
WIFEXITED(status) 如果正常死亡,返回真
WEXITSTATUS(status) 返回子进程的退出状态和0377的与,那个值。
WIFSIGNALED(status) 如果子进程被信号终止,返回真
WTERMSIG(status) 检测被几号信号终止。只有上个宏为真的时候,才使用。
返回值:
-1 错误
返回终止的子进程的pid
代码示例
- wait.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void){
pid_t pid;
int s;
//创建子进程
pid=fork();
if(pid==-1){
perror("fork");
return 1;
}
if(pid==0){
printf("child pid=%d\n" \
getpid());
//sleep(5);
getchar();
exit(-1);
}else{
//等待子进程的结束
wait(&s);
if(WIFEXITED(s)){
//子进程正常终止
printf("status:%d\n" WEXITSTATUS(s));
}
//检测子进程是否被信号终止
if(WIFSIGNALED(s)){
//输出终止子进程的信号编号
printf("signum :%d\n" \
WTERMSIG(s));
}
printf("parent...\n");
}
return 0;
}
- 执行结果
pid_t waitpid(pid_t pid int *status int options);
功能:等待进程改变状态。
参数:
pid:
< -1: pid取绝对值,如果子进程的组id等于这个绝对值,那么这个子进程就被等待。
-1:等待任意子进程
0:等待和当前进程有同一个组id的子进程
> 0 等待子进程的pid是pid参数的子进程。
status:同wait(2)参数的使用
options:
WNOHANG:非阻塞回收。
0 阻塞回收
返回值:
-1 错误
0 没有子进程退出
回收的子进程的pid
代码示例
- waitpid.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void){
pid_t pid;
int s;
//创建子进程
pid=fork();
if(pid==-1){
perror("fork");
return 1;
}
if(pid==0){
printf("child pid=%d\n" \
getpid());
//sleep(5);
getchar();
exit(-1);
}else{
//非阻塞等待子进程的结束
waitpid(-1 &s WNOHANG);
if(WIFEXITED(s)){
//子进程正常终止
printf("status:%d\n" WEXITSTATUS(s));
}
//检测子进程是否被信号终止
if(WIFSIGNALED(s)){
//输出终止子进程的信号编号
printf("signum :%d\n" \
WTERMSIG(s));
}
printf("parent...\n");
}
return 0;
}
- 执行结果
kill -[信号编号] [进程的pid]
僵尸进程子进程已经终止,但是父进程还没有回收子进程的资源,这时候的子进程处于僵尸状态,成为僵尸进程。
代码示例- zombile.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int main(void){
pid_t pid;
pid=fork();
if(pid==-1){
perror("fork");
return 1;
}
if(pid==0){
exit(0);
}else{
sleep(20);
wait(NULL);
}
return 0;
}
在进程的虚拟地址空间加载新的映像
在子进程的虚拟地址空间加载新的影像,需要使用系统提供的一个家族的函数。
execl(3)
#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[]);
execve(2)
#include <unistd.h>
int execve(const char *filename char *const argv[] \
char *const envp[]);
相同的exec
l list
v vector
p PATH
e 环境变量
返回值:
成功调用永远不返回
-1 错误 errno被设置
代码示例
- exec.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
char *const ps_argv[]={"ps" "-o" "pid ppid pgrp comm" NULL};
int main(void){
pid_t pid;
//创建子进程
pid=fork();
if(pid ==-1){
perror("fork");
return 1;
}
if(pid==0){
//加载新映像
//execl("/bin/ps" "ps" "-o" \
"pid ppid pgrp comm" NULL);
//execlp("ps" "ps" "-o" \
"pid ppid pgrp comm" NULL);
execvp("ps" ps_argv);
}else{
wait(NULL);
}
return 0;
}
#include <stdlib.h>
int system(const char *command);
功能:执行一个shell命令
参数:
command:可执行命令
返回值:
-1 错误
返回command的退出状态码。
代码示例
- system.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
int main(void){
pid_t pid;
pid=fork();
if(pid==-1){
return 1;
}
if(pid==0){
execl("./myt" "myt" NULL);
//system("myt");
exit(0);
}else{
wait(NULL);
}
return 0;
}
另外,作者在蓝桥云课上线了《Linux 操作系统原理剖析》,以 Linux 操作系统为基础对操作系统实现原理进行深入讲解,分析操作系统中的内存管理、进程管理、文件系统管理、设备管理、网络管理等几大子模块的实现原理。