----------------------------------------------------------进程学习--------------------------------------------------------
-1>进程:
进程的特点:
独立性:各个进程互不干扰
并发性:同时执行
动态性:程序的动态执行过程
异步性:每个进程的执行速度由CPU调度决定的
进程的分类:
交互式进程 >由shell终端产生和控制的进程
批处理进程 >批处理程序一般是shell脚本
守护进程 >该进程一般在后台运行,在linux启动的时候就开始执行,系统关闭才结束例如(ssh samba tftp nfs)
进程的相关操作:
进程的创建的API------> pid_t fork(void);
相关头文件: #include<sys/types.h>
#include<unistd.h>
例如:
pid_t pid = fork();
if(pid > 0){
进入父进程代码块
......
}
if(pid == 0){
进入子进程代码块
........
}
-------------------------------------------------------------------------------------------
进程的替换的API---->exec族
头文件:#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, .../* (char *) NULL */);
int execlp(const char *file, const char *arg, .../* (char *) NULL */);
int execle(const char *path, const char *arg, .../*, (char *) NULL, 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[]);
p:表示根据文件名寻找到要加载的程序,一般默认会去/bin或 /usr/bin这两个目录去寻找
没有P:表示根据路径寻找要加载的程序
l:表示以列举的方式传递被加载的程序
v:表示以数组的方式传递被加载的程序
e:表示传递环境变量的方式给被加载的程序
例如:
需要编写两个程序,运行,通过使用exec函数族对另一个程序内容进行替换
exec.c 和 exec_new.c
exec.c:
char *argv[] = {"./new",NULL};
char *encv[] = {"sssss","dddddd","mmmmmm",NULL};
int ret = execvep("bin/ls",argv,encv);
exec_new.c
extern char **environ;
main(){
printf("这是另一个进程\n");
int i = 0;
while(environ[i] != NULL){
printf("%s",environ[i]);
i++;
}
printf("\n");
}
-----------------------------------------------------------------------------------------
进程的阻塞API----> int flock(int fd, int operation)
头文件:#include <sys/file.h>
功能:
给fd(文件描述符)做 锁操作
参数:
fd:文件描述符
operation:
LOCK_SH :共享锁(上锁)
LOCK_EX:互斥锁(上锁)
LOCK_UN :解锁
LOCK_NB :不锁
进程A 进程B
LOCK_SH LOCK_SH :共享不阻塞
LOCK_SH LOCK_EX :互斥,阻塞
LOCK_EX LOCK_SH :互斥,阻塞
LOCK_EX LOCK_EX :互斥,阻塞
LOCK_SH|LOCK_NB ---->不阻塞
LOCK_EX|LOCK_NB ---->不阻塞
返回值:
成功返回0
失败返回-1并返回错误码
例如:编写两个程序(flock1.c flock2.c)
flock1.c
打开一个文件
int fd = open("1.txt",O_RDWR|O_CREAT|O_TRUNC,0666);
if(fd < 0){
perror();
exit(-1);
}
char buf[] = {"ddddDDDD\n"};
while(1){
sleep(1);
printf("1 准备上锁\n");
flock(fd,LOCK_EX);互斥锁
printf("1 上锁成功\n");
sleep(5);
write(fd,buf,strlen(buf));
printf("%s\n",buf);
printf("1 准备解锁\n");
flock(fd,LOCK_UN);
printf("1 解锁成功\n");
}
flock2.c
与flock1.c 代码类似
int fd = open("1.txt",O_RDWR|O_CREAT|O_TRUNC,0666);
if(fd < 0){
perror();
exit(-1);
}
char buf[] = {"mmmmmddddd\n"};
while(1){
sleep(1);
printf("2.准备上锁\n");
flock(fd,LOCK_EX);
printf("2.上锁成功\n");
sleep(5);
write(fd,buf,strlen(buf));
printf("%s\n",buf);
printf("2.准备解锁\n");
flock(fd,LOCK_UN);
printf("2.解锁成功\n");
}
-----------------------------------------------------------------------------------------进程的结束API-------> void _exit(int status)
头文件:#include <unistd.h>
功能:
结束进程
参数:
status:进程状态
exit(-1);---只有0和非0的区别,如是非0则代表,不正常结束
exit(0);----会认为进程是正常结束
exit和_exit的区别
exit在结束进程之前会刷新缓冲区
_exit立马结束进程,不做任何操作
return---->结束函数
-----------------------------------------------------------------------------------------
进程的资源的回收API-------> pid_t wait(int *wstatus)
pid_t waitpid(pid_t pid, int *wstatus, int options)
头文件:#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *wstatus, int options);
功能:
给子进程收尸
参数:
pid:
>0 :给特定的进程(进程ID号为pid)收尸
例子:waitpid(3543,其他参数,其他参数);
=0 :给和当前进程在同一进程组下的所有子进程收尸
=-1 :给任意子进程收尸
<-1 :给进程组ID号 |pid| 下的子进程收尸
-pid
|-pid|
wstatus:子进程的死亡状态
options:选项:
0 :阻塞等待
WNOHANG:不阻塞
WUNTRACED: also return if a child has stopped
WIFEXITED:如果子进程是正常死亡,则为true
采用WEXITSTATUS去获取子进程的状态
WIFSIGNALED:如果子进程被信号终止,则为true
采用WTERMSIG去解析信号
WIFSTOPPED:如果子进程通过传递信号而被暂停,则为true
采用WSTOPSIG去解析
返回值:
如果阻塞状态成功返回 被收尸的子进程PID号
被阻塞状态(WNOHANG)收到尸则返回子进程PID号,没收到则返回0
失败都是返回-1,并设置错误码