花钱做网站注意,wordpress搜索错误,张家界网络,深圳制作企业网站的公司目录 一、进程 1.程序和进程 2.进程的八种状态 3. 几个状态 4.关于进程常用命令
二、关于进程的函数 1.fork 2.面问 3.孤儿进程 后台进程 2. exec函数族 (只保留父子关系#xff0c;做新的事情) strtok函数
三、进程的结束
1.分类
exit和_exit的区别
wait函数…目录 一、进程 1.程序和进程 2.进程的八种状态 3. 几个状态 4.关于进程常用命令
二、关于进程的函数 1.fork 2.面问 3.孤儿进程 后台进程 2. exec函数族 (只保留父子关系做新的事情) strtok函数
三、进程的结束
1.分类
exit和_exit的区别
wait函数 waitpid函数
四、总结 一、进程 1.程序和进程 内存中正在进行(运行)中的程序。 ./a.out跑起来就是a.out对应的进程。 程序 静态 硬盘 进程 动态 内存 程序 代码 数据 代码区(text段)栈区堆区BSSData 进程 代码区(text段)栈区堆区BSSData PCB(Process Control Block) BSS存放程序中未初始化的全局变量的一块内存区域。 DATA存放程序中已初始化的全局变量的一块内存区域。 2.进程的八种状态 *D 不可中断态的睡眠态 *R 正在运行态 或者 就绪态 *S 可终端的睡眠态 *T stopped by job control signal t stopped by debugger during the tracing X 死亡态 *Z 僵尸态 3. 几个状态 通用三态图 linux系统的状态 4.关于进程常用命令 top 动态查看系统中进程 pstree -sp [pid] 查看进程树(可指定pid号) kill 发出信号 kill -l //查看可以发送的信号 18) SIGCONT //继续信号 19) SIGSTOP //暂停 9) SIGKILL //死亡信号杀死进程 kill -19 [pid] //给指定pid号的进程发送 信号 ps aux | grep a.out 查看pid号进程的状态信息 ps -eLf | grep a.out 查看pid和ppid号
二、关于进程的函数 1.fork pid_t fork(void); 通过复制主调进程创建子进程。 一次fork返回了两次 typedef int pid_t 成功 在父进程空间返回子进程pid在子进程空间返回 0 失败 父进程返回值-1 errno会被设置 2.面问 eg1如果两次fork同时前后执行会生成几个进程 4个进程 eg2 fork()fork()||fork(); 5个进程 fork() / \ fork() fork1() / \ / \ fork fork2 fork1 fork3 / \ fork2 fork4 3.孤儿进程 后台进程 子进程没有父进程就是孤儿进程将会有 init(1)-进程 收养子进程。变成 后台进程 ( ctrl c) 这个信号只能发给前台进程。 结束后台进程要用kill 子进程结束但是父进程没有对子进程收尸。那就是僵尸进程。僵尸态是有危害的消耗内存。 eg1 fork创建子进程分别打印pid
#include stdio.h
#include sys/types.h
#include unistd.hint main(void)
{pid_t pid fork();if (pid 0){perror(fork fail);return -1;}if (pid 0){printf(father pid %d ---\n,getpid());printf(pid %d,getpid());}else if (pid 0){printf(child pid %d ---\n,getpid());}printf(--pid %d --end---\n,getpid());return 0;
} 2. exec函数族 (只保留父子关系做新的事情) 通过将新进程的各个段替换当前进程的各个段来实现用来执行一个新的功能 int execl(const char *path, const char *arg, .../* (char *) NULL */); int execv(const char *path, char *const argv[]); path 代表要运行的新程序的名字 要包含路径 eg: /home/linux/fileio/mycp arg 表示要运行的程序的名字 eg: mycp ... 可变参数(要执行程序用到的参数) eg: src.txt,dest.txt,NULL结尾 l(list)和v(vector)的区别 传参的方式不同 execl( /home/linux/fileio/mycp,mycp, src.txt,dest.txt,NULL); char * const args[] {mycp, src.txt,dest.txt,NULL}; int execv( /home/linux/fileio/mycp, args); printf(---exec---code---);后续代码不执行因为段被替换 int execlp(const char *file, char *const argv[]); int execvp(const char *file, char *const argv[],char *const envp[]); p 表示 PATH系统环境变量(系统运行时侯需要的一些变量) 表示要执行的可执行文件到PATH环境变量中去寻找 execlp(ls,ls,-l,/,NULL); char *const args[] {ls,-l,/,NULL}; execlp(ls,ls,-l,/,NULL); int execle(const char *path, const char *arg, .../*, (char *) NULL, char * const envp[] */); 看要运行的程序需不需要环境变量需要就可以传。不需要的话用之前的方式运行起来就行。 int execvpe(const char *file, char *const argv[],char *const envp[]); e 表示用户环境变量 ---提供了一种方式可以给要运行的程序传递环境变量 extern char **environ; int main{ execle(/usr/bin/env,env,NULL,environ); char *const my_env[] {USERNAMElinux,PSWD123456 ,NULL}; execle(/usr/bin/env,env,NULL,my_env); execvpe(env,my_env,NULL); return 0; } strtok函数 作用提取字符串 char *strtok(char *str, const char *delim); str --- 要提取完整字符串 -- buf 如果连续的分割 填NULL delim --- 分隔标志 // ;,可以有多个分割标志 返回值: 成功 返回提取到的字符串的地址 失败 NULL eg strtok的使用
#includestdio.h
#includestring.h
int main(int argc, char const *argv[])
{char buf[1024]{ls -l ;/};
#if 0 char *s1 strtok(buf, ;);printf(s1 %s\n,s1);char *s2 strtok(NULL, ;);printf(s2 %s\n,s2);char *s3 strtok(NULL, ;);printf(s3 %s\n,s3);
#endifchar *s[5] {NULL};int i 0;s[i] strtok(buf, ;);while (s[i] strtok(NULL, ;));for ( i 0; i 5; i){printf(s[%d]%s\n,i,s[i]);}return 0;
}
eg1 实现一个shell程序 #include stdio.h
#include unistd.h
#include string.h
#include sys/wait.hint main(int argc,const char *argv[])
{char buf[1024] {0};while (1){printf(myshell$ );fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1] \0;if (strncmp(buf,exit,4) 0 || strncmp(buf,quit,4) 0){printf(exit---myshll---\n);return 0;}int i 0;char *arg[10] {NULL};arg[i] strtok(buf, );while (arg[i] strtok(NULL, ));
#if 0for (i 0; i 10; i){printf(%d:%s\n,i,arg[i]);}
#endif pid_t pid fork();if (pid 0){perror(fork fail);return -1;}if (pid 0){wait(NULL);continue;}else if (pid 0){if (execvp(arg[0],arg) 0){perror(execvp fail);return -1;}}}return 0;
} 三、进程的结束
1.分类
正常结束: 1main 中 return 2exit() //库函数 c库函数会执行io库的清理工作关闭所有 的流以及所有打开的文件。 注册清理函数atexit。 3_exit,_Exit 会关闭所有的已经打开的文件不执行清理函数。 //系统调用 //4) 主线程退出 //5主线程调用pthread_exit 异常终止: 6abort() //发送一个SIGABRT 7signal //发信号 结束了进程 kill pid -9 //8) 最后一个线程被pthread_cancle exit函数 #include stdlib.h void exit(int status); 功能: 造成进程正常结束 参数: status 带出一个状态值给到父进程 结合wait和宏才能查看状态值 return 0 自动调取一个exit函数从而调用atexit函数_exit不调用atexit函数 _exit #include unistd.h void _exit(int status); 功能: 造成进程正常结束 立刻结束 参数: status 带出一个状态值给到父进程 结合wait和宏才能查看状态值 exit和_exit的区别 区别: exit 是库函数 退出前 1.先清理IO缓存 2.调用清理函数 _exit 是系统调用 立即结束进程 atexit #include stdlib.h int atexit(void (*function)(void)); 功能: 注册一个退出清理函数 参数: function ---- 函数指针 函数类型 void func1(void) 返回值: 成功 返回0 失败 非0 ps注册顺序和调用顺序相反(有栈的结构) 状态值: status 0377 一个字节的数据 1 1 1 1 1 1 1 1 //0377 二进制 0 0 0 0 0 0 0 0 //数值 个数 256 个值 wait函数 pid_t wait(int *wstatus); 用于等待子进程的状态的变化并获取一些该子进程的信息。 三种变化 1.子进程结束 2.子进程被信号暂停(kill SIGSTOP) 3.子进程因信号被回恢复SIGCONT 参数: status 获取子进程退出时的状态信息(要用宏才能提取出来) //被调修改主调的方式 返回值: 成功 返回状态改变了的子进程的pid 失败 -1 如果不关心其退出状态一般用NULL表示 注意: wait 本身是个阻塞操作(只有有子进程时才阻塞没有子进程时立即返回wait调用失败) //子进程结束 父进程在子进程结束后用wait进行资源回收和状态的获取称为关心。 不进行资源回收的结束的子进程是僵尸态。 宏 //正常结束 WIFEXITED(wstatus) //判断子进程是否是正常结束 //正常结束 则为真 WEXITSTATUS(wstatus) //使用这个宏去那返回值 //异常结束 WIFSIGNALED(wstatus) //判断子进程是否是被信号结束 WTERMSIG(wstatus) //获得 结束子进程的那个信号编号 eg 1 WIFEXITED(wstatus)和 WEXITSTATUS(wstatus)
#include stdio.h
#include unistd.h
#include sys/wait.h
#include stdlib.hint main(void)
{pid_t pid fork();if (pid 0){perror(fork fail);return -1;}if (pid 0){sleep(3);printf(---wait----child---\n);int status;wait(status);printf(status %d\n,status);if (WIFEXITED(status)){printf(child status %d\n,WEXITSTATUS(status));}}else if (pid 0){printf(---child----exit---\n);exit(99);}return 0;
}eg 1 WIFSIGNALED(wstatus) 和 WTERMSIG(wstatus)
#include stdio.h
#include unistd.h
#include sys/wait.h
#include stdlib.hint main(void)
{pid_t pid fork();if (pid 0){perror(fork fail);return -1;}if (pid 0){sleep(3);printf(---wait----child---\n);int status;//wait(status);//waitpid(-1,status,WNOHANG);waitpid(-1,status,0);printf(status %d\n,status);if (WIFEXITED(status)){printf(child status %d\n,WEXITSTATUS(status));}}else if (pid 0){printf(---child----exit---\n);exit(99);}return 0;
}eg3 wait的使用
#include stdio.h
#include unistd.h
#include sys/wait.h
#include stdlib.hint main(void)
{pid_t pid fork();if (pid 0){perror(fork fail);return -1;}if (pid 0){ sleep(3);printf(---wait----child---\n);int status;wait(status);printf(status%d\n,status);if(WIFEXITED(status)){printf(child status %d\n,WEXITSTATUS(status));}}else if (pid 0){printf(---child----exit---\n);exit(99);}return 0;
} eg4 无人机状态模拟
#include stdio.h
#include unistd.h
#include sys/wait.h
#include stdlib.hvoid do_fly(void)
{int i 0;while (i 5){printf(---%s---\n,__FUNCTION__);i;sleep(1);}exit(88);
}void do_video(void)
{int i 0;while (i 3){printf(---%s---\n,__FUNCTION__);i;sleep(1);}exit(77);
}
void do_transmit(void)
{int i 0;while (i 4){printf(---%s---\n,__FUNCTION__);i;sleep(1);}exit(66);
}
void do_store(void)
{int i 0;while (i 6){printf(---%s---\n,__FUNCTION__);i;sleep(1);}exit(55);
}int main(void)
{int i 0;pid_t pid 0;for (i 0; i 4; i){pid fork();if (pid 0){perror(fork fail);return -1;}if (pid 0)break;}if (pid 0){int status;for (i 0; i 4; i){wait(status);if (WIFEXITED(status)){switch(WEXITSTATUS(status)){case 55:printf(do_store exit---\n);break;case 66:printf(do_transmit exit---\n);break;case 77:printf(do_video exit---\n);break;case 88:printf(do_fly exit---\n);break;}}}}else if (pid 0){switch(i){case 0:do_fly();break;case 1:do_video();break;case 2:do_transmit();break;case 3:do_store();break;}}return 0;
}waitpid函数 pid_t waitpid(pid_t pid, int *wstatus, int options); 功能: 等待子进程状态改变 参数: pid -1 meaning wait for any child process whose process group ID is equal to the absolute value of pid. eg: -100 表示等待 进程组ID 为 |-100| 这个进程组中的任意子进程 -1 meaning wait for any child process. 表示等待 当前父进程的任意子进程 0 meaning wait for any child process whose process group ID is equal to that of the calling process. 等待 进程组ID 等于 父进程pid的那个进程组中的任意子进程 0 meaning wait for the child whose process ID is equal to the value of pid. eg: 100 等待 进程pid 为 100的这个子进程状态改变 wstatus //与wait的参数类似 如果不关心其退出状态一般用NULL表示 获取准确状态值也是用 options // 0 //阻塞调用 WNOHANG //非阻塞 不断的看子进程状态有没有改变没有改变就返回了。有改变了将资源回收并进行if判断下面的操作。 waitpid(-1, wstatus, 0); //等价于 wait(wstatus) 四、总结 //进程 创建 --- fork 运行 //1.跟父进程类似 事情 //2.独立运行一个新程序 ---exec函数 //3.运行多个不同任务 结束 正常结束 //1.return //main //2.exit //3._exit 异常结束 //4.abort //信号 //5.signal //发其它信号 进程结束是两种特殊状态 孤儿进程 僵尸进程 --- wait/waitpid