目录
1.linux进程
1.1 基本知识
进程是操作系统分配资源的基本单位,是一个动态的实体;
2 进程编程
2.1 创建进程
创建进程有两种方式,一种是操作系统创建如init进程,一种是父进程创建。区别在于,操作系统创建的进程,一般不存在隶属关系,而父进程创建的,存在隶属关系。
创建进程的函数主要有,fork 和 vfork,区别在于fork创建的进程,完全复制父进程的资源,而vfork创建的集成,共享父进程的地址空间,也就是说,子进程对地址空间的数据修改,父进程是可见的。 同时vfork 必须的子进程先运行,exit、exec后,父进程才会调用。
/*fork 和 vfork 对比,创建处分别注释,编译运行 即可看见差异*/
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#define COMPILE_FORK
//#define COMPILE_VFORK 二选一
int g_var = 10;
int main(void)
{
pid_t pid;
int i;
int var = 1;
printf("vfork fork compare code \r\n");
#ifdef COMPILE_FORK
pid = fork(); /*fork 方式*/
#endif
#ifdef COMPILE_VFORK
pid = vfork(); /*vfork 方式*/
#endif
switch(pid)
{
case 0: /*child*/
{
i = 3;
while(i-- > 0)
{
printf("child process running \r\n");
g_var++;
var++;
sleep(1); /*仅仅调试用*/
}
printf("child g_var:%d var:%d \r\n",g_var,var);
break;
}
case -1: /*failed*/
{
perror("failed create process\n");
exit(1);
}
default: /*parent*/
{
i = 5;
while (i-- > 0)
{
printf("parent process running\r\n");
g_var++;
var++;
sleep(1); /*仅仅调试用*/
}
printf("parent g_var:%d var:%d \r\n",g_var,var);
exit(0);
}
}
}
2.2 创建守护进程
守护进程指的是没有和终端相连,后台运行,一般用于周期性执行某些任务。
#include <stdio.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>
/*@desp, 创建守护进程
*@return ,0 成功,-1 失败
*/
int daemon_init(void);
int main(void)
{
time_t current;
daemon_int();
syslog(LOG_USER|LOG_INFO,"守护进程 \r\n");/*无终端,使用系统log*/
while(1)
{
sleep(5);/*测试代码*/
time(¤t);
syslog(LOG_USER|LOG_INFO,"守护进程-系统时间[\t%s\t\t] \n",ctime(¤t));/*无终端,使用系统log*/
}
}
int daemon_init(void)
{
int pid;
int i;
signal(SIGTTOU,SIG_IGN); /*忽略终端OUT信号*/
signal(SIGTTIN,SIG_IGN); /*忽略终端IN信号*/
signal(SIGTSTP,SIG_IGN; /*忽略stop信号*/
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;
}
2.3 退出进程
子进程 先于 父进程 终止,父进程未调用wait等待,子进程进入僵死状态(耗费资源)
子进程 先于 父进程 终止,父进程调用wait等待,父进程等待子进程结束(推荐)
2.4 执行进程程序
使用exec 执行另一个可执行程序,代替当前进程的执行程序。
exec 本质是废弃原来的数据段 对战段,为新程序分配数据段和堆栈段,保留进程ID。
/*exec 家族函数*/
#include <unistd.h>
extern char **environ;
/*通过路径名,调用可执行文件*/
int execl(const char *path,const char *arg,...);
/*通过路径名,调用可执行文件*/
int execle(const char *path,const char *arg,...);
/*通过路径名,调用可执行文件*/
int execv(const char *path,char *const argv[]);
int execlp(const char *file,const char *arg,...);
int execvp(const char *file,char *const argv[]);
int execvpe(const char *file,char *const argv[],char *const evnp[]);
/*调用测试进程 test_process*/
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(argc,char *argv[],char **env)
{
pid_t pid;
int var_stat;
pid = fork();
if (pid == 0)/*child*/
{
printf("child process pid: %d parent pid:%d \r\n",getpid(),getppid());
printf("child process uid: %d gid:%d \r\n",getuid(),getgid());
execve("test_process",argv,env);/*执行新的代码*/
printf("never run here \n");
exit(0);
}
else if (pid < 0)/*failed*/
{
perror("create process failed\r\n");
exit(1);
}
else
{
printf("parent process\r\n");
}
wait(&var_stat);
exit(0);
}
2.5 等待进程结束
#include <sys/types.h>
#include <sys/wait.h>
/* @desp, 父进程暂停执行,直到子进程结束
* @param,stat 状态信息
* @return, 返回子进程pid
*/
pid_t wait(int *stat);
/* @desp, 等待特定子进程结束
* @param,stat 状态信息
* @param,options 状态信息
* @return, 返回子进程pid
*/
pid_t witpid(pid_t pid,int *stat,int options)
2.6 进程id
#include <sys/types.h>
#include <unistd.h>
/* @desp, 获取进程id
* @return, 返回进程pid
*/
pid_t getpid(void);
/*进程具有root权限,则函数将实际用户Id,有效用户Id,设置为参数uid
* 进程不具有root权限,但uid=实际用户id,则只将有效用户Id设置为uid,不改变实际用户Id
* 若不满足,则返回-1
*/
/* @desp, 设置进程用户id
* @param,uid 用户id
* @return, 0返回成功,其他失败
*/
int setuid(uid_t uid);
/* @desp, 设置进程组id
* @param,gid 组Id
* @return, 0返回成功,其他失败
*/
int setgid(gid_t gid);