Linux 进程学习及使用

一、进程的相关概念
进程:正在执行的程序
程序:可执行的二进制文件
僵尸进程:当前进程运行结束,但其资源没有被回收。产生僵尸:子进程退出父进程不使用wait 父进程不能退出。
孤儿进程:当前进程的父进程提前结束,此进程被称为孤儿进程。孤儿进程会被1号进程收养,并最终由1号进程回收资源。

进程的内存结构:采用虚拟内存管理技术,使得每个进程都有独立的地址空间。该地址空间是大小为4GB的线性虚拟空间。4GB的地址空间被分为两个部分,用户空间和内核空间,0-3GB是用户空间,3-4GB为内核空间。用户进程在通常情况下只能访问用户空间的虚拟地址,不能访问内核空间的虚拟地址,只有用户进行系统调用时才会访问到内核空间。每当进程切换时,用户空间就会跟着变化,但内核空间由内核负责映射,它并不会跟着进程改变,是固定的。
进程内存布局分为四个不同的段:
1)文本段,包含程序的源指令。
2)数据段,包含了静态变量。
3)堆,动态内存分区区域。
4) 栈,动态增长与收缩的段,保存本地变量。

二、进程相关函数学习

getpid() 获得当前进程的进程号
getppid() 获得当前进程的父进程号
exec函数 在进程中启动另一个进程执行
system 在进程中开始另一个进程
fork 和vfork 从已存在的进程中复制一个新进程
sleep 让进程暂停执行一段时间
exit 终止进程
_exit 终止进程
wait 暂停父进程,等待子进程
waitpid 暂停父进程,等待子进程

1、getpid函数
原型:pid_t getpid(void);
功能:获取当前进程号
头文件:
#include <sys/types.h>
#include <unistd.h>
参数:无
返回值:返回当前进程号
2、getppid函数
原型:pid_t getppid(void);
功能:获取当前进程的父进程号
头文件:
#include <sys/types.h>
#include <unistd.h>
参数:无
返回值:返回当前进程的父进程号
3、fork函数
原型:pid_t fork(void);
功能:创建进程
头文件:
#include <unistd.h>
参数:无
返回值:
0:子进程
子进程PID(大于0的整数):父进程
<0:出错
注:fork函数调用一次返回两次,返回值可以作为区分是父进程还是子进程。
4、vfork函数
原型:pid_t vfork(void);
功能:创建进程
头文件:
#include <sys/types.h>
#include <unistd.h>
参数:无
返回值:
0:子进程
子进程PID(大于0的整数):父进程
<0:出错

注:
1)vfork和fork的区别:
fork:子进程拷贝父进程的数据段
vfork:子进程与父进程共享数据段

fork:父、子进程的执行次序不确定
vfork:子程先运行,父程后运行
5、wait函数
原型:pid_t wait(int *status);
功能:阻塞进程,等待某个子进程退出
头文件:
#include <sys/types.h>
#include <sys/wait.h>
参数:
status:用来保存子进程退出时的状态
NULL:表示忽略子进程退出时的状态
!NULL:表示保存子进程退出的状态
返回值:
成功:子进程的进程号
失败:-1
6、waitpid函数
原型:pid_t waitpid(pid_t pid, int *status, int options);
功能:等待阻塞某个指定的子进程的退出
头文件:
#include <sys/types.h>
#include <sys/wait.h>
参数:
pid:指定的子进程号
pid>0:只等待进程ID等于pid的子进程,不管已经有其他子进程运行结束退出,只要指定的子进程还没有结束,waitpid就会一直等下去。
pid=0:等待其组ID等于调用进程的组ID的任一子进程
pid=-1:等待任何一个子进程退出,此时和wait作用一样。
pid<-1:等待其组ID等于PID的绝对值的任一子进程
status:用来保存子进程退出时的状态
NULL:表示忽略子进程退出时的状态
!NULL:表示保存子进程退出的状态
options:选项
WNOHANG:若由pid指定的子进程并不立即可用,则waitpid不阻塞,此时返回值为0
WUNTRACED:若某实现支持作业控制,则由pid指定的任一子进程状态已暂停,且其状态自暂停以来还未报告过,则返回其状态
0:阻塞父进程,等待子进程退出
返回值:
成功:子进程的进程号
使用选项WNOHANG且没有子进程结束时:0
失败:-1
7、exit函数
原型:void exit(int status);
功能:终止进程的执行
头文件:
#include <stdlib.h>
参数:
status:指示进程退出的状态
0:正常终止
-1:异常终止
返回值:无
8、_exit函数
原型:void _exit(int status);
功能:终止进程
头文件:#include <unistd.h>
参数:
status:指示进程退出的状态
0:正常终止
-1:异常终止
返回值:无

注:
exit()和_exit函数的区别:_exit直接使进程终止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构;exit要检查文件的打开情况,把文件缓冲区中的内容写回文件。
9、sleep函数
原型:unsigned int sleep(unsigned int seconds);
功能:函数调用使得进程挂起一段时间,直到指定时间完成
头文件:#include<unistd.h>
参数:
seconds:指定的秒数
返回值:
成功:0
失败:-1
10、system函数
原型:int system(const char *command);
功能:调用fork产生子进程,由子进程来调用执行command命令
头文件:#include <stdlib.h>
参数:
command:命令字符串
返回值:
如果没有找到/bin/sh,system返回127;
如果出现其他错误则返回-1;
如果执行成功则返回command的代码。
但是如果command为NULL,system返回一个非0值,否则返回0。
注:system()通过调用/bin/sh –c command来执行具体的command命令
11、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[]);

参数说明:
path:是要执行的二进制文件或脚本的完整的目录路径
argv:表示启动程序所带的参数,一般第一个参数为要执行命令名,不是带路径且arg必须以NULL结束
envp是指向用于执行execed程序的专门环境的指针。
file:可以只给出文件名,系统会自动从环境变量“$PATH”所包含的路径中进行查找。

示例:

char *str[]={"ls",NULL};
execve("/bin/ls",str,NULL);

execl("/bin/ls", "ls", "-al", "/etc/passwd", (char *) 0);
//execl()其中后缀"l"代表list也就是参数列表的意思,
//第一参数path字符指针所指向要执行的文件路径, 
//接下来的参数代表执行该文件时传递的参数列表:argv[0],argv[1]... 
//最后一个参数须用空指针NULL作结束。


示例 1int execl(const char * path,const char * arg,....);
//execl()用来执行参数path字符串所代表的文件路径,
//接下来的参数代表执行该文件时传递过去的argv(0)、argv[1]……,
//最后一个参数必须用空指针(NULL)作结束。
#include<unistd.h>
main()
{
execl(/bin/ls”,”ls”,-al”,/etc/passwd”,(char * )0);
}
/*执行/bin/ls -al /etc/passwd */
-rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd

示例2int execlp(const char * file,const char * arg,……)//execlp()会从PATH 环境变量所指的目录中查找符合参数file的文件名,找到后便执行该文件,
//然后将第二个以后的参数当做该文件的argv[0]、argv[1]……,
//最后一个参数必须用空指针(NULL)作结束。
/* 执行ls -al /etc/passwd execlp()会依PATH 变量中的/bin找到/bin/ls */
#include<unistd.h>
main()
{
execlp(“ls”,”ls”,-al”,/etc/passwd”,(char *)0);
}
-rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd

示例3int execv (const char * path, char * const argv[ ]);
//execv()用来执行参数path字符串所代表的文件路径,
//与execl()不同的地方在于execve()只需两个参数,
//第二个参数利用数组指针来传递给执行文件。
/* 执行/bin/ls -al /etc/passwd */
#include<unistd.h>
main()
{
char * argv[ ]={“ls”,-al”,/etc/passwd”,(char*) }};
execv(/bin/ls”,argv);
}
-rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd

示例4:
int execve(const char * filename,char * const argv[ ],char * const envp[ ]);
//execve()用来执行参数filename字符串所代表的文件路径,
//第二个参数系利用数组指针来传递给执行文件,
//最后一个参数则为传递给执行文件的新环境变量数组。
#include<unistd.h>
main()
{
char * argv[ ]={“ls”,-al”,/etc/passwd”,(char *)0};
char * envp[ ]={“PATH=/bin”,0}
execve(/bin/ls”,argv,envp);
}
-rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd

示例5:
int execvp(const char *file ,char * const argv []);
//execvp()会从PATH 环境变量所指的目录中查找符合参数file 的文件名,
//找到后便执行该文件,然后将第二个参数argv传给该欲执行的文件。
#include<unistd.h>
main()
{
char * argv[ ] ={ “ls”,-al”,/etc/passwd”,0};
execvp(“ls”,argv);
}
-rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd

注:
1)当进程调用一种exec函数时,该进程完全由新程序代换,而新程序则从其main函数开始执行。因为调用exec并不创建新进程,所以前后的进程ID并未改变。exec只是用另一个新程序替换了当前进程的正文、数据、堆和栈段。用另一个新程序替换了当前进程的正文、数据、堆和栈段。当前进程的正文都被替换了,那么execl后的语句,即便execl退出了,都不会被执行。
2)名字中含有l的函数:希望接受以逗号分隔的参数列表,列表以NULL指针作为结束标志,这些参数将传递给被执行的程序。
名字中包v的函数:则接受一个向量,也就是以空结尾的字符串的指针数组。这个数组必须以一个NULL指针作为结束标志。不过,需要注意的是,有时候可能那个NULL,需要写成(char *)0。

示例:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

void main(void)
{
    pid_t pid1, pid2;
    pid1 = fork();
    if(pid1 < 0) {
        printf("error in fork!\n");
    }else if(pid1 == 0) {
        printf("this is child1 process, process id is %d, parent id is %d\n", getpid(),getppid());
    }else {
        wait(NULL);
        printf("this is parent1 process, process id is %d, child id is %d\n", getpid(),pid1);
    }
    exit(0);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值