进程
进程是在系统中能够独立运行的活动实体。由(机器指令)PCB,数据,堆栈组成。
引入进程的目的:为了使多个程序能够并发的执行,提高系统的吞吐量。
进程调度方式:
<1>非抢占式方式
<2>抢占式方式:优先权原则,短作业优先,时间片原则。
进程调度算法:
<1>先来先服务调度算法
<2>短作业优先调度算法
<3>高优先权调度算法
<4>基于时间片轮转调度算法
Linux系统中的进程类型
<1>交互进程:由shell控制和运行,可以在前台或后台运行。
<2>批处理进程:该进程被提交到队列中顺序执行。
<3>守护进程:该进程在后台运行。
Linux运行状态
<1>运行态
<2>等待态
<3>停止态
<4>死亡态
调度进程
ps 查看系统中的进程 aux-->显示该进程所有信息 elf ajx
top 动态显示系统进程 q结束
kill 结束进程
bg 将挂起的进程放到后台执行
fg 把后台的进程放到前台运行
===================================================================
进程创建:fork()
头文件:#include <sys/types.h>
#include <unistd.h>
函数体:pid_t fork(void);
返回值:0--->子进程 子进程的PID---->父进程 -1---->出错
例:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
extern int errno;
int main()
{
int a=10;
pid_t pid;
if(0 > (pid = fork()))
{
fprintf(stderr,"error :%s",strerror(errno));
return -1;
}
else if(0 == pid)
{
a=100;
printf("this is child %d\n",getpid());
printf("this is parent %d\n",getppid());
printf("a===%d\n",a);
}
else
{
sleep(2);
printf("this is my child PID %d\n",pid);
printf("this is myself PID %d\n",getpid());
printf("a---%d\n",a);
}
printf("==================\n");
return 0;
}
【注意】:
<1>父进程先exit(),子进程成为孤儿进程由init回收。
<2>子进程先exit(),变为等待父进程回收资源,如果父进程不退出,子进程变成僵尸进程。
exec()函数族
exec()用途:如果某个进程想同时执行另一个程序,他就可以调用fork()函数创建子进程,然后在子进程中调用任何一个exec()函数,就可以让子进程执行新的程序。
头文件: #include <unistd.h>
函数体: int execl(const char *path,const char *arg,...);
int execv(const char *path,char *argv[]);
int execle(const char *path,char *arg,...char *envp[]);
int ececve(const char *path,char *argv[],chr *envp[]);
int execlp(cosnt char *file,char *arg);
int execvp(const char *file,char *argv[]);
例子:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
extern int errno;
int main()
{
pid_t pid;
if(0 > (pid = fork()))
{
fprintf(stderr,"error :%s\n",strerror(errno));
return -1;
}
else if(0 == pid)
{
pid_t psd;
if(0 > (psd = fork()))
{
fprintf(stderr,"error :%s\n",strerror(errno));
return -1;
}
else if(0 == psd)
{
char *argv[]={"cat","1.txt",NULL};
execv("/bin/cat",argv);
}
else
{
execl("/bin/ls","1","-la","/program/",NULL);
}
}
else
{
int status;
wait(&status);
execl("/bin/cat","1","1.txt",NULL);
}
return 0;
}
: int execve(const char *path,char *const argv[],char *const envp[]);
例子:
s1.c文件
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 int main(int argc, char *argv[])
7 {
8 char *buf = getenv("PATH1");
9 printf("envirment: %s\n",buf);
10
11 return 0;
12 }
s2.c文件
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/types.h>
5
6 int main()
7 {
8 char *argv1[]={"./s1","1",NULL};
9 char *argv2[]={"PATH1=/usr/lib",NULL};
10
11 execve("s1",argv1,argv2);
12 printf("=========\n");
13 return 0;
14 }
编译:
gcc -o s1 s1.c
gcc -o s2 s2.c
./s2
========================================================================
exit()与_exit()
头文件:exit :#include <stdlib.h>
_exit :#include <unistd.h>
函数体: exit :void exit(int status); //status 是参数值 0表示正常结束
_exit :void _exit(int status);
区别:
exit() :使用exit()系统会检查文件的打开情况,把文件缓冲区的内容写回到文件。
_exit() :使用_exit()直接会使进程终止运行,清除其使用的内存空间,并销毁内核中的各种数据结构。
例子:
<1>#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("-----sunxu-----");
printf("-----hello-----");
exit(0);
return 0; 输出:-----sunxu----------hello-----
}
<2>#include <stdio.h>
#include <unistd.h>
int main()
{
printf("-----sunxu-----\n");
printf("-----hello-----");
_exit(0);
return 0; 输出:-----sunxu-----
}
wait与waitpid
头文件: :#include <sys/types.h>
#include <sys/wait.h>
函数体: pid_t wait(int *status);
pid_t waitpid(pid_t pid,int *status,int options);
区别:
wait() :使用该函数使进程阻塞,直到任意一个子进程结束或者是该进程收到一个信号为止。成功返回子进程的进程号,失败-1。status保存子进程退出时的状态。
waitpid():可以指定的等待某个子进程的结束以及等待的方式。(阻塞与非阻塞)。返回子进程的进程号。
例子:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/wait.h>
#include <stdlib.h>
extern int errno;
int main()
{
pid_t pid;
if(0 > (pid = fork()))
{
fprintf(stderr,"error :%s",strerror(errno));
return -1;
}
else if(0 == pid)
{
printf("this is child %d\n",getpid());
printf("this is parent %d\n",getppid());
sleep(3);
exit(88);
}
else
{
sleep(4);
int status;
pid_t pd;
//pd=wait(&status);
pd=waitpid(pid,&status,0);
printf("pd===%d\n",pd);
printf("status++%d\n",status);
printf("this is my child PID %d\n",pid);
printf("this is myself PID %d\n",getpid());
}
return 0;
}
atexit()函数
用途 :设置程序正常结束前调用的函数,相当于入栈与出栈。
头文件 :#include <stdlib.h>
函数体 : int atexit(void (*function)(void));
例子:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
void fun1(void)
{
printf("fun1\n");
}
void fun2(void)
{
printf("fun2\n");
}
int main(int argc, char *argv[])
{
atexit(fun1);
atexit(fun2);
exit(0);
}
=========================================================
Linux守护进程
守护进程是Liunx中的后台服务进程,在系统启动时开始运行,在系统关闭时终止。
Linux中从终端开始运行的进程都会依附于这个终端,这个终端称为这些进程的控制终端。当控制终端被关闭时,相应的进程都会被自动关闭。但守护进程不会依附于这个终端。
Linux守护进程编写步骤:
1.创建子进程,父进程退出。
2.在子进程中创建新会话。
3.改变当前目录 #通常是让"/" 或"/tmp"作为守护进程的当前工作目录。
4.从设文件权限掩码。
5.关闭文件描述符。
流程: 开始--->fork() exit() --->setsid() ---->chdir("/")--->umask(0)----close()--->结束
例如:
创建一个守护进程init.c文件
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
extern int errno;
void init_daemon(void)
{
int pid;
int i;
if(pid = fork())
{
exit(0);
}
else if(0 > pid)
{
fprintf(stderr,"%d:---%s\n",__LINE__,strerror(errno));
exit(-1);
}
setsid(); //第一个子进程成为新的会话组长和进程组长,并与控制终端分离。
for(i=0 ; i < getdtablesize();i++)
close(i);
chdir("/home");
umask(0);
return ;
}
创建一个main.c测试文件
#include <stdio.h>
#include <time.h>
void init_daemon(void);
int main()
{
FILE *fp;
time_t t;
init_daemon();
while(1)
{
sleep(2);
if((fp = fopen("test.log","a"))!=NULL)
{
t = time(0);
fprintf(fp,"I am here at %sn",asctime(localtime(&t)));
fclose(fp);
}
}
return 0;
}
编译:<1> gcc -o fun init.c main.c
<2> ./fun
查看:tail -f /home/test.log
尊重作者,请转明来处:追Dream梦http://blog.csdn.net/pzhsunxu/article/details/7798319