1, Linux进程组成:
1)进程控制块(PCB) 存放进程标志信息 现场信息 控制信息 是进程的标志(随进程的创建而创建,消亡而消亡)
2)进程程序块 存放进程执行的指令代码
3)进程内核栈 保存 中断/异常现场 以及 执行函数调用时存放参数和返回地址(这个有点像汇编里面的call ret?忘了 = =), 只当进程在内核态下工作才使用
4)进程数据块 存放私有数据,用户栈,线程只包含前三个
2, 创建进程:
1)fork( ) 创建新进程, 新进程完全复制父进程的资源(副本?)而且直到开始更改时才复制(效率问题), 执行上独立于父进程, 与父进程 通过pipe等方式通信
2)vfork( ) 与fork( )相似, 不同的是,新进程不会重新复制父进程的资源, 而是共享父进程的资源。而且执行时会block父进程, 直到exec( )或exit( ). 相当于函数调用。。
3)clone( ) 创建线程, 其使用为 clone( (void*)func, stack, clone_flag, arg); 返回值应该是线程的句柄, 其中:
func 为执行程序,函数名为void* func(int arg),
stack 为线程使用的内核栈, 经常是 stack = (char*)malloc(STACK_FRAME); stack += STACK_FRAME; 请求内存空间
flags 可以是CLONE_VM, CLONE_FS, CLONE_FILE CLONE_SIGHAND 和CLONE_PID的组合(即 "|")
而arg 则应为func的参数
例子程序 vfork 与 fork函数的比较:
在这里说一下, 执行完fork后 会生成两个方向的程序(复制下方的程序代码组成的进程?),fork会返回两个值(成功创建的话), 一个给父进程(pid就是子进程的进程ID 正数), 一个给子进程(pid = 0), 如果失败的话, 返回-1
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
int main(void)
{
int data = 0;
pid_t pid;
int choose = 0;
while ( (choose = getchar()) != 'q') {
switch (choose) {
case '1':
pid = fork();
if (pid < 0) {
printf ("Error!\n");
}
if (pid == 0) {
data++;
exit(0);
}
wait(pid);
if (pid > 0) {
printf("data is %d\n", data);
}
break;
case '2':
pid = vfork();
if (pid < 0) {
printf ("Error!\n");
}
if (pid == 0) {
data++;
exit(0);
}
wait(pid);
if (pid > 0) {
printf("data is %d\n", data);
}
break;
default:
break;
}
}
}
执行结果为:
1
data is 0
2
data is 1
q
表明: vfork( ) 的内存空间与父进程共用, 而fork( ) 是“独立”的“新建”的内存空间(在需要修改的时候方创建副本, 效率问题, 总不能只需只读的情况下还要复制大量的数据吧)
4)exec( ) 替换原来的新程序(代码段),废弃原有的数据段与堆栈段, 只使用进程号,可以用于vfork/ exec 创建新进程
#include <errno.h>
#include <error.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char command[256];
int main ()
{
int rtn;
bool flag = true;
while (flag) {
flag = false;
printf(">");
fgets( command, 256, stdin);
command[strlen(command)-1] = 0;
if ( fork() == 0) {
execlp(command, command, NULL);
printf("here rtn is %d\n", rtn); //这一句居然不执行, 不知为何, 其但求在接下来的学习可以获知
perror ( command );
exit(-1);
} else {
wait (&rtn);
printf("child process return %d\n", rtn);
}
}
return 0;
}
P.S. 编译时要用g++