下面就是我对进程的初步理解:
大家都知道,操作系统最核心的概念就是进程。它与程序最大的区别就是进程是动态的,其次就在于进程是保留在内存中的代码,而程序是保存在硬盘上的可执行的代码。在Linux操作系统中,每个进程都是通过唯一的进程ID标识的。
<1>关于获取进程的各种标识符
pid_t getpid(); //获得进程ID
pid_t getppid(); // 获得父进程ID
pid_t getuid(); //获得进程的实际用户ID
pid_t geteuid(); //获得进程的有效用户ID
pid_t getgid(); //获得进程的实际组ID
pid_t getegid(); // 获得进程的有效组ID
<2> Linux 进程状态
其中,进程有以下几个状态:运行状态R(runnnable),可中断等待状态S(sleeping),不可中断状态D(uninterruptible sleep),僵死状态Z(zombile),停止状态T(traced and stopped) 。
<3>进程的种种~
在进程中比较常用的函数有:a、fork();用于创建一个新进程;b、exit();用于终止进程;c、exec();用于执行一个应用进程;d、wait();将父进程挂起等待子进程;e、getpid();获得的那个前进程的进程ID;f、nice();改变进程的优先级。
还有就是关于进程的内存映像,其中一个程序的生成需要进行:预编译、编译、汇编、链接这四个阶段。进程在内存中的映像呢,其实就是操作系统将可执行程序由硬盘复制到内存中,然后内核在内核在内存中如何存放可执行程序文件的。关于内存映像这块,我自己也。。。。大家最好看一下我师父的博客:http://toqianmo.sinaapp.com/2013/05/23/jinchengyanzhongdexianxingdizhikongjian.html
嗯嗯,说明一点,程序只有被加载到内存中才会被分配堆栈,所以可执行程序没有堆栈。
<4> 关于创建进程函数fork();和vfork();
大家都知道,当一个进程向其父进程传递其终止信息时,就意味着这个进程的整个生命周期的结束。此时,该进程占用的所有资源包括ID也被全部释放。(摘自《Linux C 编程实战》)其中,init进程是以调用kernel_thread(int, NULL, 0);这个函数的形式进行的,是其它所有进程的父进程,孤儿进程就是被它收养的。
a、fork();函数原型
#include <sys/types.h>
#include <unisted.h>
pid_t fork(void);
一般情况下,函数都只有一个返回值,但fork();函数却有两个返回值,一个是子进程的返回值为0,另一个是父进程的返回值为新创建的子进程的进程ID。fork();之后是父进程先执行还是子进程先执行,这就要看你的操作系统的内核喽~
由于操作系统一般会让进程具有同等的执行权,所以一般会让你的父子进程交替执行。
b、vfork();函数原型
#include <sys/types.h>
#include <unisted.h>
pid_t vfork(void);
vfork();函数也有两个返回值,与fork();函数相同;但是两者之间又有很大的区别:
(1) 、fork();创建的子进程只是对父进程的完全复制;而vfork();创建的子进程则是共享父进程的地址空间;
(2)、fork();创建进程时并不能保证是先执行父进程还是子进程;而vfork();保证了子进程先运行,当它调用exec或exit之后父进程才可能被调度进行。
<5>守护进程
一提到进程,大家不免会说,进程那块守护进程算是难点了。(这块不太懂,所以就只能抄书了><!!!)
首先,了解一下它的概念吧,守护进程是指在后台运行的、没有控制终端与之相连的进程。它独立于控制终端,通常周期性的执行某种任务。守护进程是一种很好用的进程,Linux 的大多数服务器都是用守护进程的方式实现的,如Inted,Web服务器进程http等。
在编写守护进程时尽量要避免产生不必要的交互,那么调用setsid创建一个新对话期就OK啦~~
还有好多好多有关进程的知识,大家赶快啃《Linux C编程实战》吧 !那真的是一本好书。。。
重点来了,这是今天最大的收获,可以帮你真正理解创建进程函数fork();是个神奇东东哦~
fork之奇葩 1:
#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i = 0;
for (i = 0; i < 2; i++)
{
fork();
printf("-");
}
return 0;
}
恩,这个程序就是典型的一个创建进程的程序,其中在for循环中有一个创建进程的函数fork();额。。。太不好意思了,本来有一个插图就是说明这个过程的,但是我不会那个插图,所以没办法啦,用文字叙述吧。
首先这个程序的结果就是--------,即8个-,那么为什么是8个呢?经过求教,弄懂了这个东西。假设最开始的父进程用A表示,在i = 0,时A先fork一次为B,此时A和B的内存中都有一个“-”,有也不存在清除缓冲区这一步骤,所以在i = 1,时A再fork一次为C,此时A和C中都各有一个“-”,然后进行语句printf("-");这样呢,A和C的内存单元里又会有2个“-”,同理B也一样,所以就轻而易举的得到了答案,就是8个“-”哟~~
试想一下,如果在循环以外加一条语句printf("\n");程序的输出结果又有神魔不同呢?
fork之奇葩2:
#include <stdio.h>
#include <sys/stypes.h>
#include <unistd.h>
int main()
{
int i = 0;
for ( i = 0; i < 2; i ++)
{
fork();
printf("-\n");
}
return 0;
}
这个程序的结果呢,可能在意料之中也可能在意料之外哦,如果不仔细看呢,很可能会觉得这个程序和上面的程序是一样的、、哈哈,那么你就错啦,这两个可是有质的的差别呢。就单单一个"\n",就导致了结果有点差异,先想想答案会是神魔呢?
先来讲一下吧,首先当i=0时,A会fork一个B,而因为有"\n"的存在,所以在i=1时,当A和B同时再分别fork一个C和D时,C和D的内存中本身就不会有一个“-”,因此,这次的结果比上面那道程序的少了2个“-”,So,结果会有6个“-”。
这个就是最近学的,还有要谢谢露纹学姐今天为我们带来的详细讲解,thx~