linux进程(二)之基础
原创
©著作权归作者所有:来自51CTO博客作者vaynedu的原创作品,请联系作者获取转载授权,否则将追究法律责任
1. 操作系统最核心的概念就是进程,进程是操作系统资源管理的最小单位。进程是一个动态的实体,是程序的一次执行过程,线程在进程的内部,它是比进程能独立运行的基本单位,所有线程共享同一个进程的所有资源。
2.每个进程都是通过唯一的进程ID标识的,linux的一个进程中由3个部分组成,代码段,数据段,堆栈段
3.linux进程状态,运行状态R(runnable),可中断等待状态S(sleeping),不可中断等待状态D(uninterruptible sleep),僵死状态Z(zombile),停止状态T(traced or stopped)
4.进程控制包括创建进程、执行新进程、退出进程以及改变进程优先级,fork,exit,exec,wait,getpid,nice
5.进程的内存映像,linux下C程序的生成分为四个阶段:预编译、编译、汇编、链接。编译器gcc经过预编译、编译、汇编3个步骤将源程序文件转化为目标文件。如果程序中有多个目标文件或者程序中使用楼库函数,编译器还要将所有的目标文件或者所需要的库链接起来,最后生成可执行程序。当程序执行的时候,操作系统将可执行程序复制到内存中。
6.进程的内存映像是指内核在内存中如何存放可执行程序文件。在将程序转换为进程的过程中,操作系统将可执行程序由硬盘复制到内存中。
7.创建进程fork1.c fork2.c
<span style="font-size:18px;">#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
pid_t pid;
printf("process creation study\n");
pid = fork();
switch(pid){
case 0:
printf("child process is running,CurPid is %d,Parent is %d\n",pid,getppid());
break;
case -1:
printf("process creation failed\n");
break;
default:
printf("parent process is running,Childpid is %d,Parentpid is %d\n",pid,getpid());
break;
}
// exit(-1);
return 0;
}
</span>
fork之后是父进程先执行还是子进程先执行是不确定的,这取决于内核所使用的调度算法。
<span style="font-size:18px;">#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
pid_t pid;
char * msg;
int k;
printf("process creation study\n");
pid = fork();
switch(pid){
case 0:
msg = "Child process is runing ";
k = 3;
break;
case -1:
perror("process creation failed\n");
break;
default:
msg = "parent process is runing";
k = 5;
break;
}
while(k > 0)
{
puts(msg);
sleep(1);
k--;
}
// exit(-1);
return 0;
</span>
8.孤儿进程
<span style="font-size:18px;">#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid;
pid = fork();
switch(pid){
case 0:
while(1){
printf("a background process ,pid:%d,parentid:%d\n",getpid(),getppid());
sleep(3);
}
case -1:
perror("process creation failed\n");
exit(-1);
default:
printf("I am parent process,my pid is %d\n",getpid());
exit(0);
}
return 0;
</span>
9.vfork函数(有一篇文章会详细比较)
<span style="font-size:18px;">#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int globVar = 5;
int main(void){
pid_t pid;
int i;
int var = 1 ;
printf("fork is diffrent with vfork \n");
//pid = fork();
pid = vfork();
switch(pid){
case 0:
i = 3;
while(i-- > 0)
{
printf("Child process is running\n");
globVar++;
var++;
sleep(1);
}
printf("child's globVar = %d,var = %d\n",globVar,var);
break;
case -1:
perror("process creation failed\n");
break;
default:
i=5;
while(i-- > 0)
{
printf("parent process is running\n");
globVar++;
var++;
sleep(1);
}
printf("parent's globVar is %d,var = %d\n",globVar,var);
exit(0);
}
return 0;
}
</span>
10 创建守护进程
守护进程(daemon)是指在后台运行、没有控制终端与之相连的进程,它独立与控制终端,通常周期性的执行某种任务。守护进程是非常有用的,linux的大多数服务器就是守护进程的方式实现的。
<span style="font-size:18px;">#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <time.h>
#include <syslog.h>
int init_daemon(void)
{
int pid;
int i;
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
signal(SIGTSTP,SIG_IGN);
signal(SIGHUP,SIG_IGN);
pid = fork();
if(pid > 0){
exit(0);
}
else if(pid<0){
return -1;
}
setsid();
pid = fork();
if(pid > 0){
exit(0);
}
else if(pid<0){
return -1;
}
for(i=0;i< NOFILE;close(i++));
chdir("/");
umask(0);
signal (SIGCHLD,SIG_IGN);
return 0;
}
int main(void){
time_t now;
init_daemon();
syslog(LOG_USER |LOG_INFO,"测试守护进程!\n");
while(1){
sleep(8);
time(&now);
syslog(LOG_USER |LOG_INFO,"系统时间:\t%s\t\t\n",ctime(&now));
}
return 0;
}
</span>
11.执行新程序,用fork和vfork创建子进程后,子进程通常会调用exec函数来执行另外一个程序。系统调用exec用于执行一个可执行的程序代替当前进程的执行映像
<span style="font-size:18px;">#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
extern char **environ;
int main(int argc,char *argv[]){
int i;
printf("Argument:\n");
for(i=0;i<argc;i++){
printf("argv[%d] is %s\n",i,argv[i]);
}
printf("Enviroment:\n");
for(i = 0;environ[i]!=NULL;i++)
printf("%s\n",environ[i]);
return 0;
}
</span>
12 exec函数的用法 processimage.c和execve.c
<span style="font-size:18px;">#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc,char * argv[],char **environ){
int i;
printf("I am a process image!\n");
printf("My pid = %d, parentpid = %d\n",getpid(),getppid());
printf("uid = %d,gid = %d\n",getuid(),getgid());
for(i=0;i<argc;i++)
printf("argv[%d]:%s\n",i,argv[i]);
return 0;
}
</span>
<span style="font-size:18px;">#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc,char *argv[],char **environ)
{
pid_t pid;
int stat_val;
printf("Exec example@\n");
pid = fork();
switch(pid){
case -1:
perror("process creation failed\n");
exit(1);
case 0:
printf("child process is running\n");
printf("My pid =%d,parentpid = %d\n",getpid(),getppid());
printf("uid = %d,gid = %d\n",getuid(),getgid());
execve("processimage",argv,environ);
printf("process never go to here\n");
exit(0);
default:
printf("parent process is running \n");
break;
}
wait(&stat_val);
exit(0);
}
</span>
可以通过./execve test extcve
子进程永远不会执行到
<span style="font-size:18px;">printf("process never go to here\n");</span>
因为子进程已经被新的执行映像替代