进程控制 --chlaws

                    进程控制 --chlaws
在文章之前需要简单的了解下相关的函数和一些概念。若已经知道,觉的没有必要再看了,可以略过前面这部分。


1首先是关于一些隶属于进程控制这块的函数 做个简单的说明,若是还有不明白的就使用man命令来参看manual。
关于获得进程ID号和父进程ID的函数
getpid()/getppid()

关于获取实际用户和有效用户ID。
注意实际用户ID是指标识运行该进程的的用户,有效用户ID是指标识以什么用户身份来运行进程。
例子: user A:创建了一个文件,而这个程序以root身份来执行,这个文件执行时就具有了root权限。
此时实际用户ID就是A,有效用户ID就是root用户的ID
getuid()/geteuid()  ,

关于获取实际组ID和有效组ID
getgid()/getegid()
对应的有设置用户ID和组ID的函数
setuid(uid)/setgid(gid)

fork  创建一个新进程(完全复制父进程资源) //vfork 子进程规定是先执行,和父进程共享空间
exit 
exec 家族函数,用于执行一个新的应用程序,可以传递参数给新程序。具体的可以使用man 3 exec查看

wait/waitpid 挂起父进程,等待子进程终止

检查wait和waitpid所返回状态的几个宏
WIFEXITED(val) 子进程正常结束,该宏返回一个非零值,表示真。若异常结束,返回0,表示假
WEXITSTUS(val) 若WIFEXITED返回非零,它返回子进程中exit参数的低8位
WIFSIGNALED(val) 异常结束,返回非0表示真
WTERMSIG(val)    WIFSIGNALED返回非0,则该宏返回使子进程异常终止的信号编号
WIFSTOPPED(val)  子进程暂停,返回非0表示真
WSTOPSIG(val)    WIFSTOPPED返回非0,该宏返回使子进程暂停的信号编号

nice  改变进程优先级,其内部实现是通过调用getpriority/setpriority来实现的
实现函数:
int nice(int increment)
{
    int oldp = getpriority(PRIO_PROCESS,getpid());
    return setpriority(PRIO_PROCESS,getpid(),oldp+increment); 
}


2.一些基本的概念需要知道,具体的如下

程序转化为进程的步骤
1.内核将程序读入内存,为程序分配内存空间。
2.内核为该进程分配pid和PCB其他所需的资源
3. 内核为该进程保存pid及状态信息,把进程放到运行队列等待执行。
程序转化为进程后可以被操作系统的调度程序调度执行。


进程的状态(可以通过ps进行查看 如ps -ux 查看当前用户的进程状态)
R 运行状态
S  可中断等待状态
D  不可中断等待
Z  僵死状态
T  停止状态
<  高优先级进程
N   低优先级进程
L    内存锁页
s    会话首进程
l     多线程进程
+  进程位于前台进程组




创建守护进程的步骤:
1.忽略终端I/O信号,STOP信号
2.结束父进程,使子进程成为后台进程
3.使用setsid()建立一个新的进程组,在这个新的进程组中,子进程成为这个进程组的首进程,以使该进程脱离所有终端。
4.再次建立一个子进程,退出父进程,保证该进程不是进程组长,同时让该进程无法再次打开一个新的终端。
5.关闭所有从父进程继承下来的不再需要的文件描述符
6.改变工作目录,使得进程不与任何文件联系
7.将文件屏蔽字设置为0
8.忽略SIGCHILD信号

setsid  创建一个新对话期。常用于创建守护进程。控制终端,登录会话和进程组通常是从父进程继承下来的,守护进程要摆脱他们,不受影响,其方法是调用setsid使进程成为一个会话组长。


3.具体代码实例

//note:守护进程的代码
#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> int init_daemon(void) { int pid; int i; /*忽略终端I/O信号,STOP信号*/ 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("/"); /*将文件当时创建屏蔽字设置为0*/ umask(0); /*忽略SIGCHLD信号*/ signal(SIGCHLD,SIG_IGN); return 0; } int main() { 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)); } }

//note:myshell的实现

#include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> #include<unistd.h> #include<sys/types.h> #include<dirent.h> #include<sys/stat.h> #include<fcntl.h> #include<sys/wait.h> #define normal 0 #define out_direct 1 #define in_direct 2 #define have_pipe 3 void print_prompt(void); void input_argument(char* buf); void explain_input(char* buf, int* argcount,char arglist[100][256]); void do_cmd(int argcount,char arglist[100][256]); int find_command(char* command); int main() { char* buf; int argcount; char arglist[100][256]; if((buf = (char*)malloc(256)) == NULL){ perror("malloc error"); exit(1); } while(1){ print_prompt(); input_argument(buf); if(!strcmp(buf,"exit/n") || !strcmp(buf,"logout/n")){ printf("exit my shell/n"); break; } argcount = 0; explain_input(buf,&argcount,arglist); do_cmd(argcount,arglist); } free(buf); return 0; } void print_prompt(void) { printf("/n[my shell]$ "); } void input_argument(char* buf) { char c; char* l =buf; while( (c=getchar()) != '/n'){ *buf++=c; } *buf++ = '/n'; *buf = '/0'; } void explain_input(char* buf, int* argcount,char arglist[100][256]) { char *p,*q; int i=0; p = buf; while(*p!='/0'){ if(*p=='/n') break; if(*p==' ') p++; else{ i=0; q=p; while(*q!=' ' && *q!='/n'){ arglist[*argcount][i++]=*q; q++; } arglist[*argcount][i] = '/0'; *argcount += 1; p=q; } } } void do_cmd(int argcount,char arglist[100][256]) { int flag=0; int flag_count=0; pid_t pid; char* arg[100]; int i; int background=0; int status; int j; char* argnext[100]; pid_t pid2; int fd2; int status2; for(i=0; i< argcount; i++){ arg[i] = (char*)arglist[i]; } arg[argcount] = NULL; for(i=0; i< argcount; i++){ if(strncmp(arg[i],"&",1)==0){ if(i==argcount-1){//last words is "&" background = 1; arg[argcount-1]=NULL; break; } else{ printf("command wrong/n"); return; } } } for(i=0; i<argcount; i++){ if(strcmp(arg[i],">")==0){ flag_count++; flag = out_direct; if(arg[i+1] == NULL)//last words is ">" flag_count++; } if(strcmp(arg[i],"<") == 0){ flag_count++; flag = in_direct; if(i == 0) //first words is "<" flag_count++; } if(strcmp(arg[i],"|")==0){ flag_count++; flag = have_pipe; //first or last words is "|" if(arg[i+1] == NULL) flag_count++; if(i == 0) flag_count++; } if(flag_count > 1){ printf("flag_count :is %d > 1 so command error/n",flag_count); return; } } char* file=NULL; switch(flag){ case out_direct: for(i=0; arg[i]!=NULL; i++){ if(strcmp(arg[i],">")==0){ file = arg[i+1]; arg[i]=NULL; } } break; case in_direct: for(i=0; arg[i]!=NULL; i++){ if(strcmp(arg[i],"<")==0){ file = arg[i+1]; arg[i]=NULL; } } break; case have_pipe: //int j; //char* argnext[100]; for(i=0; arg[i]!=NULL; i++){ if(strcmp(arg[i],"|")==0){ arg[i]=NULL; for(j=i+1;arg[j]!=NULL;j++){ argnext[j-i-1]=arg[j]; } argnext[j-i-1]=NULL; break; } } default: break; } int fd; if((pid = fork())<0){ printf("create process error/n"); exit(1); } if(pid==0/* && find_command(arg[0])*/){ switch(flag){ case normal: execvp(arg[0],arg); exit(0); break; case out_direct: if( !find_command(arg[0])){ printf("command not find/n"); exit(0); } fd = open(file,O_RDWR|O_CREAT|O_TRUNC,0644); printf("fd : %d/n",fd); dup2(fd,1); execvp(arg[0],arg); exit(0); break; case in_direct: fd = open(file,O_RDONLY); dup2(fd,0); execvp(arg[0],arg); exit(0); break; case have_pipe: /* pid_t pid2; int fd2; int status2; */ if((pid2 = fork())<0){ printf("fork pid2 error/n"); exit(0); } if(pid2 == 0){ if(!find_command(arg[0])){ printf("command not find/n"); exit(0); } fd2 = open("/tmp/yoursfile",O_CREAT|O_RDWR|O_TRUNC,0644); dup2(fd2,1); execvp(arg[0],arg); exit(0); } if( waitpid(pid2,&status2,0) == -1) printf("wait for child process error/n"); if(!find_command(argnext[0])){ printf("command not find/n"); exit(0); } fd2 = open("/tmp/yoursfile",O_RDONLY); dup2(fd2,0); execvp(argnext[0],argnext); /* if(remove("/tmp/yoursfile")!=0){ printf("remove file error/n"); } exit(0); */ break; default: break; } //execvp(arg[0],arg); } if( waitpid(pid,&status,0) == -1) printf("wait for child process error/n"); } int find_command(char* command) { char* path[]={"./","/bin","/usr/bin",NULL}; int i = 0; if(strncmp("./",command,2)==0) command = command+2; DIR* dir; struct dirent* ptr; while(path[i] != NULL){ dir = opendir(path[i]); while((ptr=readdir(dir))!=NULL){ if(strcmp(ptr->d_name,command)==0){ closedir(dir); return 1; } } closedir(dir); i++; } return 0; }

你可能感兴趣的:(进程控制 --chlaws)