1、什么是进程?
(1)概念:进程是正在执行的程序的实例,是linux的基本调度单位;程序写好之后,放在内存,程序在运行时,进程就创建了,通俗的说,程序是“死的”,进程是“活的”;
(2)组成元素:
1)进程的当前上下文(context),是进程当前的执行状态
2)当前执行目录
3)访问文件和目录
4)访问权限
5)内存和其它分配给进程的系统资源
(3)进程标识符pid
1)父子进程:
父进程标识符:ppid
子进程标识符 :pid
//均为非零的整数
2)一个PID唯一标识一个进程
3)祖先进程的进程号为1,叫做init进程,它是linux启动后第一个执行的进程,init引导系统启动守护进程,并且运行必要的程序
4)PID的用法:
《1》是创建唯一的文件或者目录名
《2》把PID写入日志文件,作为日志消息的一部分
二、如何创建进程?
(1)system:用于调用shell,执行一个指定的命令;
(2)fork:用于创建一个新的进程, 该进程几乎是当前进程的一个完全拷贝;
(3)execve可以在进程中用另外的进程来替换当前运行的进程;
1、得到PID的方法:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 #include<sys/types.h>
5
6 int main()
7 {
8 //test pid****************
9 printf("PID = %d\n",getpid() );
10 printf("PPID = %d\n",getppid() );
11 return 0;
12 }
2、察看最大进程数
$cd /proc
$cd sys
$cd kernel
$cat pid_max
如下所示:
3、UID用户号
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 #include<sys/types.h>
5 #include<pwd.h>
6 int main()
7 {
8 //**********test getlogin *************
9 char* login = getlogin();
10 struct passwd *ps = getpwnam(login);
11 printf("user name = %s\n",ps->pw_name);
12 printf("uid = %d \n",ps->pw_uid);
13 printf("home dir = %s \n",ps->pw_dir);
14 return 0;
15 }
//getlogin()函数返回执行程序的用户登录名和用户号
三、fork()函数
(1)特性:
pid_t fork(void);
fork( )执行后:
成功:向父进程返回子进程的PID,并向子进程返回0,这也就意味着fork( )一次调用,两次返回;
失败:向父进程返回-1,并且不创建子进程
fork( )创建的新进程是和父进程一样的副本;
fork( )创建出来的父子进程之间是异步的,没有依赖性;
(2)创建:
(1)无法预计父进程在子进程之前还是之后运行,它们的执行是无序的,是异步的;
(2)异步就意味着父子进程代码无依赖性
(3)fork( )可能失败,原因是因为系统上已经运行了太多的进程,超过了它所允许的最大进程数;
(4)fork( )过程包括将父进程全部内存映像给子进程,过程缓慢
(5)调用vfork( )也创建新的进程,但不产生父进程的副本
[linux已经使用了写时复制技术,因此linu的vfork( )和UNIX中的vfork( )一样快]
四、execve()函数
**(1)特性:**execve启动一个新程序,替换原有进程,故被执行的进程PID不变,是用被执行的程序完全替换了调用进程的映像
int execve(const char*path,const char*argv,char* const envp[]);
//const char*path: 要执行文件的完整路径
//const char*argv:传递给程序完整的参数列表
//char* const envp[]:指向execed程序的环境指针,可设为NULL
ls的实现
#include<stdio.h>
2 #include<stdlib.h>
3 #include<sys/types.h>
4 #include<unistd.h>
5 #include<pwd.h>
6 int main()
44 {
45 char *args[] = {"bin/ls","-l",NULL};
46 execve("/bin/ls",args,NULL);//执行到这里,程序结束
47 printf("end\n");
48 return 0;
49 }
1、执行 ./fork结果
2、执行 ls -l结果
五、比较:
system:创建两个不同的进程,进程间相互独立,pid不同
fork:创建两个一样的进程,自进程是父进程的一个副本,但pid不一样
execve:创建一个进程,替换原来进程,pid不变
wait( )和waitpid( )
pid_t wait(int* status);
pid_t waitpid(pid_t pid,int * status,int options);
//pid_t pid:等待进程的PID
//int * status: 保存子进程的退出状态
//int options
pid的取值:
-1等待任何PGID等于PID的绝对值子进程
1等待任何子进程
0等待任何PGID等于调用进程的子进程
0等待PID等于pid的子进程
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<sys/types.h>
4 #include<unistd.h>
5 #include<pwd.h>
6
7 int main()
8 {
9 pid_t pid = fork();
10 int status;
11 if(pid == -1)
12 {
13 printf("fork filed\n");
14 return 0;
15 }
16 if(pid == 0)
17 {
18 printf("child process start\n");
19 sleep(2);
20 printf("child process end\n");
21 return 100;
22 }
23 else
24 {
25 printf("parent process start\n");
26 wait(&status);
//出错一:
27 // printf("status = %d\n",status);//打印status要借助WEXITSTATUS( )
//正确调用:
28 printf("status = %d\n",WEXITSTATUS(status) );
//显示status的状态,必须使用WEXITSTATUS函数
29
30 printf("parent process end\n");
31 return 0;
32 }
出错一的结果:
正确调用结果: