linux 系统编程-学习笔记7-进程/fork/vfork/exec函数族
2014-10-10 20:23
477 查看
进程:程序的执行实例被称为进程。
u-boot ==>Image ==>根文件系统==>init进程(1)
==>exec执行进程==>启动代码==>main{==>传入环境变量
exit/return ==>1)刷新缓冲区,2)关闭所有打开的文件描述符,3)调用清理函数 ==>系统
_exit/_Exit ==>系统
}
==================================================================================
进程的操作:
1.进程的创建
2.进程的执行
3.进程的退出
进程的几种状态:
1.等待/就绪态
2.运行态
3.终止态
4.僵尸态
===================================================================================
创建一个新的进程:
pid_t fork(void); (pid_t -->int)
fork之后会有两个返回值:
> 0 : 返回的值是新建子进程的ID==>返回给父进程
= 0 : 返回的是子进程
= -1: 错误
父进程fork一个子进程之后,子进程继承父进程的资源空间(几乎所有的)
==>之后,父,子进程自己拥有独立的资源空间
___________________________________________
typedef __kernel_pid_t pid_t;`
typedef int __kernel_pid_t;
___________________________________________
pid_t getpid(void);
:获取本进程的进程ID
pid_t getppid(void);
:过去本进程的父进程ID
===============================================
进程间切换条件:
(子进程切换到父进程)
1.时间片结束
2.子进程执行结束
3.子进程被阻塞
4.子进程被中断
5.被优先级高(父进程)抢占
注意:保护现场(目的是能切换回来)
====================================================
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
功能:等待子进程返回,子进程返回的状态保存在变量status中,如果不关系则填NULL,
wait返回所等待的子进程的进程ID
注意:如果父进程不调用wait/waitpid等待子进程返回,回收其资源,则该子进程变成僵尸进程
僵尸进程:进程结束之后,其所占用的资源没有被释放,则称之为僵尸进程
___________________________________________________________________
通过status中的值可以判断子进程退出的状态:
WIFEXITED(status)
正常返回,返回的值由子进程中exit/_exit/return返回的值确定
WEXITSTATUS(status)
:获取返回的值
WIFSIGNALED(status)
:被信号打断
WTERMSIG(status)
:获取到打断该子进程的信号
==============================================================
pid_t waitpid(pid_t pid, int *status, int options);
waitpid(-1, &status, 0);//功能和wait是一样的
pid_t vfork(void);
1.功能同fork几乎一样
相同点:
1.功能同fork一样,创建一个新的进程
2.vfork之后会有两个返回值:
> 0 : 返回的值是新建子进程的ID==>返回给父进程
= 0 : 返回的是子进程
= -1: 错误
___________________________________________
不同点:
1.fork : 父进程fork一个子进程之后,子进程继承父进程的资源空间(几乎所有的)
==>之后,父,子进程自己拥有独立的资源空间
vfork:父,子进程共享资源空间
2.fork :父,子进程谁先运行,由内核确定
vfork: 保证子进程先运行
==>调用exec执行进程
==>所以只有调用exit退出子进程之后父进程才能执行
================================================================================
exec函数族:
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[]);
l:表示跟上一系列的参数
p:表示可以自动的去匹配路径,不给必绝对路径
e:表示可以传入环境变量参数数组
v:表示所有的参数可以通过数组传递
path/file: 命令 (绝对路径/相对路径)
arg : 参数列表
===========================================================================================
前面的五个exec函数族都是由execve封装而来的,真正的系统调用是execve
int execve(const char *filename, char *const argv[],
char *const envp[]);
filname : 文件命名/命令
argv : 命令参数选项的字符串数组
envp : 环境变量数组
u-boot ==>Image ==>根文件系统==>init进程(1)
==>exec执行进程==>启动代码==>main{==>传入环境变量
exit/return ==>1)刷新缓冲区,2)关闭所有打开的文件描述符,3)调用清理函数 ==>系统
_exit/_Exit ==>系统
}
==================================================================================
进程的操作:
1.进程的创建
2.进程的执行
3.进程的退出
进程的几种状态:
1.等待/就绪态
2.运行态
3.终止态
4.僵尸态
===================================================================================
创建一个新的进程:
pid_t fork(void); (pid_t -->int)
fork之后会有两个返回值:
> 0 : 返回的值是新建子进程的ID==>返回给父进程
= 0 : 返回的是子进程
= -1: 错误
父进程fork一个子进程之后,子进程继承父进程的资源空间(几乎所有的)
==>之后,父,子进程自己拥有独立的资源空间
___________________________________________
typedef __kernel_pid_t pid_t;`
typedef int __kernel_pid_t;
___________________________________________
pid_t getpid(void);
:获取本进程的进程ID
pid_t getppid(void);
:过去本进程的父进程ID
===============================================
进程间切换条件:
(子进程切换到父进程)
1.时间片结束
2.子进程执行结束
3.子进程被阻塞
4.子进程被中断
5.被优先级高(父进程)抢占
注意:保护现场(目的是能切换回来)
====================================================
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
功能:等待子进程返回,子进程返回的状态保存在变量status中,如果不关系则填NULL,
wait返回所等待的子进程的进程ID
注意:如果父进程不调用wait/waitpid等待子进程返回,回收其资源,则该子进程变成僵尸进程
僵尸进程:进程结束之后,其所占用的资源没有被释放,则称之为僵尸进程
___________________________________________________________________
通过status中的值可以判断子进程退出的状态:
WIFEXITED(status)
正常返回,返回的值由子进程中exit/_exit/return返回的值确定
WEXITSTATUS(status)
:获取返回的值
WIFSIGNALED(status)
:被信号打断
WTERMSIG(status)
:获取到打断该子进程的信号
==============================================================
pid_t waitpid(pid_t pid, int *status, int options);
waitpid(-1, &status, 0);//功能和wait是一样的
pid_t vfork(void);
1.功能同fork几乎一样
相同点:
1.功能同fork一样,创建一个新的进程
2.vfork之后会有两个返回值:
> 0 : 返回的值是新建子进程的ID==>返回给父进程
= 0 : 返回的是子进程
= -1: 错误
___________________________________________
不同点:
1.fork : 父进程fork一个子进程之后,子进程继承父进程的资源空间(几乎所有的)
==>之后,父,子进程自己拥有独立的资源空间
vfork:父,子进程共享资源空间
2.fork :父,子进程谁先运行,由内核确定
vfork: 保证子进程先运行
==>调用exec执行进程
==>所以只有调用exit退出子进程之后父进程才能执行
================================================================================
exec函数族:
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[]);
l:表示跟上一系列的参数
p:表示可以自动的去匹配路径,不给必绝对路径
e:表示可以传入环境变量参数数组
v:表示所有的参数可以通过数组传递
path/file: 命令 (绝对路径/相对路径)
arg : 参数列表
===========================================================================================
前面的五个exec函数族都是由execve封装而来的,真正的系统调用是execve
int execve(const char *filename, char *const argv[],
char *const envp[]);
filname : 文件命名/命令
argv : 命令参数选项的字符串数组
envp : 环境变量数组
/*练习:实现一个简单的shell终端.*/ #include <stdio.h> #include <sys/types.h> #include <pwd.h> #include <shadow.h> #include <unistd.h> #include <string.h> #include <stdlib.h> struct user { char username[100]; //用户名 char psd[100]; //原始密码 char salt[100]; //密码种子 char cmd[1024]; //命令 }; struct user user; int login(void); void show_shell(void); void get_commond(void); void do_commond(void); int main(int argc, char *argv[]) { /*用户登录*/ if(-1 == login()) { printf("\nlogin faild .......\n"); return -1; } while(1) { show_shell(); //显示shell终端 get_commond(); //获取命令 do_commond(); //处理命令 } return 0; } /******************************************** *功能:判断用户名和密码是否匹配 *返回值: * 匹配:返回0 * 错误:返回-1 * *****************************************/ int login(void) { int ret; struct passwd *pw = NULL; struct spwd *sp = NULL; char *dol = NULL; char *pssd = NULL; system("clear"); /*输入用户名*/ write(1,"username : ",strlen("username : ")); ret= read(0,user.username,sizeof(user.username)-1); if(ret > 0) { user.username[ret-1] = '\0'; } /*输入用户密码**/ write(1,"passwd : ",strlen("passwd : ")); system("stty -echo -raw"); ret = read(0,user.psd,sizeof(user.psd)); if(ret > 0) { user.psd[ret-1] = '\0'; } system("stty echo"); /*判断用户是否有密码*/ pw = getpwnam(user.username); if(NULL == pw) { return -1; } if(strcmp(pw->pw_passwd,"x")) { //没有密码 return -1; } /*获取用户加密密码*/ sp = getspnam(user.username); if(NULL == sp) { return -1; } strcpy(user.salt,sp->sp_pwdp); dol = strrchr(user.salt,'$'); if(NULL == dol) { return -1; } dol++; *dol = '\0'; /*通过crypt进行密码加密*/ pssd = (char *)crypt(user.psd,user.salt); if(NULL == pssd) { return -1; } if(strcmp(pssd,sp->sp_pwdp) == 0) { system("clear"); printf("login success.....\n"); sleep(2); return 0; } else { return -1; } } /*显示shell终端*/ void show_shell(void) { char path[100] = {0}; /*获取用户当前的绝对路径*/ getcwd(path,99); printf("%s@:%s&&& ",user.username,path); fflush(stdout); } /*获取命令*/ void get_commond(void) { int ret; memset(user.cmd,0,sizeof(user.cmd)); ret = read(0,user.cmd,sizeof(user.cmd)); if(ret > 0) { user.cmd[ret-1] = '\0'; } } /**前面的空格处理*/ void eat_white(char *str) { int len; int i; i = 0; len = strlen(str); while(1) { if(isblank(str[i])) { i++; } else { break; } } memmove((void *)&str[0],(void *)&str[i],len-i+1); } /*处理命令*/ void do_commond(void) { pid_t pid; eat_white(user.cmd); if(strncmp(user.cmd,"exit",4) == 0) { exit(0); //退出进程 } else if(strncmp(user.cmd,"cd",2) == 0) { chdir(strchr(user.cmd,' ')+1); //切换路径 } else { pid = fork(); if(0 == pid) {//子进程 execlp("/bin/sh","sh","-c",user.cmd,NULL); } else if(pid > 0) { wait(NULL); } else { perror("fork"); exit(-1); } } } /****************************************************** char *strchr(const char *s, int c); 功能是从一个字符串的开头查找字符c,返回第一次查找到的位置 ******************************************************/
相关文章推荐
- linux 系统编程学习笔记三
- LINUX C系统编程学习笔记-----------文件编程
- Linux编程学习笔记--proc文件系统 http://www.cnblogs.com/weichsel/archive/2012/06/23/2559613.html
- Linux系统编程学习笔记-open函数
- linux 系统编程学习笔记四
- LINUX C系统编程学习笔记-----------进程通信(二)
- Linux-Unix系统编程手册学习笔记
- Linux 编程学习笔记----文档管理系统
- linux 系统编程-学习笔记9--线程的同步互斥锁、读写锁/select/poll
- LINUX C系统编程学习笔记-----------进程编程
- Linux编程学习笔记--proc文件系统
- 【linux高级环境编程学习笔记四】消息队列进程通信
- linux 系统编程-学习笔记8--信号/线程
- linux 系统编程学习笔记一
- Linux系统学习笔记:进程
- Linux/Unix C编程之系统函数文件读写 学习笔记
- linux 系统编程学习笔记四
- Linux学习笔记-----进程管理-查看系统健康状态
- linux系统编程-学习笔记4-chmod/access/chown/link/truncate
- linux 系统编程-学习笔记1