uc_day06

来源:互联网 发布:非网络rpg手机游戏 编辑:程序博客网 时间:2024/06/05 21:56
一,进程
1,ps 查看当前系统的进程信息
PID TTY          TIME CMD
 2757 pts/0    00:00:00 bash
 2881 pts/0    00:00:00 ps
默认显示与当前终端相关的进程
ps -f//当前详细信息
ps -e//所有进程


UNIX-----Solari
守护进程,Daemon进程,服务进程。


S休眠状态
O可运行状态(就绪)
R运行状态
T挂起状体(和休眠状态基本一样,休眠是主动的,挂起是被动的)
Z僵尸进程(僵死进程)


Linux:进程的状态比较多


2,进程间的关系(父子关系)
init(1)


1)父进程启动子进程后,父子进程同时执行。如果子进程先结束,子进程给父进程发信号,
父进程回收子进程的相关资源
2)父进程启动子进程后,父子进程同时运行。如果父进程先结束,子进程马上认init作为自己的父进程。
init叫linux的孤儿院
3)父进程启动子进程后,父子进程同时运行。如果子进程先结束,子进程给父进程发信号,
但是父进程没有及时回收子进程的资源或子进程没来得及发信号,子进程就成僵尸进程了。
子进程已经结束,父进程的进程表中存在子进程的标志,所以僵尸进程杀不死


二,进程描述符
进程ID是唯一的,但可以重用。当一个进程终止时,其进程ID就可以再次使用
进程ID非负整数表示


延迟重用


三,
getpid()//获取进程id
getppid()//获取父id
getuid()//获取当前用户的属主,返回有效身份
geteuid()//获取当前用户的属主,返回的也是有效身份
#include<stdio.h>
#include<unistd.h>
int main(){
  printf("pid:%d\n",getpid());
  return 0;
}


四,fork() 创建进程
fork是通过复制自己来创建子进程的。全部复制一个子进程,底层通过clone函数
父子进程没有规定谁先运行,但是在linux有一个机制,子进程先执行
子进程从fork快要结束的时候执行,从fork后面开始执行


fork函数一次调用,返回两次,父进程返回一次,子进程返回一次。子进程返回0
父进程返回子进程的pid
#include<stdio.h>
#include<unistd.h>


int main(){
  printf("程序开始执行\n");
  fork();
  printf("程序执行结束\n");
  return 0;
}


#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main(){
  printf("程序开始执行\n");
  pid_t pid = fork();
  printf("pid=%d,程序执行结束\n",pid);
  return 0;
}


fork2.c
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
int main(){
  printf("程序开始执行\n");
  pid_t pid = fork();
  if(pid == -1){}
  if(pid == 0){//子进程
     printf("我是子进程,pid=%d,我的父进程是:%d\n",getpid(),getppid());
  }else{//父进程
    printf("我是父进程,pid=%d,我的子进程是:%d\n",getpid(),pid);
  }
  printf("%d进程结束运行\n",getpid());
  return 0;
}
结果:
possible@ubuntu:~/Desktop/test$ gcc fork2.c
possible@ubuntu:~/Desktop/test$ ./a.out 
程序开始执行
我是父进程,pid=3836,我的子进程是:3837
3836进程结束运行
possible@ubuntu:~/Desktop/test$ 我是子进程,pid=3837,我的父进程是:1
3837进程结束运行


#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>
int i1 = 100;
int main(){
   int i2 = 10;
   pid_t pid = fork();
   int i3 = 1000;
   char* str = malloc(20);
   strcpy(str,"abcdef");
   if(pid == -1){
     perror("子进程创建失败");
     exit(-1);
   }
   if(pid == 0){//子进程
     i1 = 200;
     i2 = 20;
     i3 = 2000;
     str[0] = 'A';
     printf("in child i1=%d\n",i1);
     printf("in child i2=%d\n",i2);
     printf("in child i3=%d\n",i3);
     printf("in child str=%s\n",str);
   }else{//父进程
     printf("in father i1=%d\n",i1);
     printf("in father i2=%d\n",i2);
     printf("in father i3=%d\n",i3);
     printf("in father str=%s\n",str);
     exit(-1);
   }
   return 0;
}
注:全局区,栈区,堆区,缓冲区都会复制




fork4.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<string.h>


int main(){
  int fd = open("a.txt",O_RDWR|0_CREAT,0666);
  if(fd == -1){}
  int pid = fork();
  if(pid == 0){//子进程
    for(char c='A', c<='Z',c++){
      write(fd,&c,1);
      sleep(1);
    }   
    exit(0);
  }
  //父进程
  char c;
  for(c='a'; c<='z'; c++){
      write(fd,&c,1);
      sleep(1);
  }
  return 0;
  return 0;
}
注:文件表没有被复制,因为文件表不是进程的一部分,子进程和父进程指向同一个文件


五,fork失败的原因
系统中有太多的进程
实际用户ID的进程总数已经超过系统限制
                                                                           
六,vfork()
和fork()不同的是,没有复制父进程的东西,而是空的


七,进程终止的情况
main函数执行return,在其他函数中return只能导致函数执行结束
调用exit函数(在终止进程之前,会先调用atexit注册的函数,调用_Exit终止进程,标C)
调用_exit(会立即终止 UC)或_Exit(标C,调用_exit终止进程)


atexit()用于注册进程在退出时调用的函数
#include<stdio.h>
#include<stdlib.h>


void fa(){
  printf("开始退出进程....\n");
  exit(0);
}
void at(){
printf("这句话在进程结束之前调用\n");
}
int main(){
  atexit(at);
  fa();
  printf("这句话打印不出来\n");
}


八,wait()----等待子进程结束
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
#include<stdlib.h>
int main(){
  pid_t pid = fork();
  if(pid == 0){
    printf("子进程开始运行,即将进入睡眠\n");
    sleep(3);
    printf("子进程运行结束\n");
    exit(0);
  }


  //父进程
  printf("父进程运行,运行的子进程是%d\n",pid);
  printf("父进程等待子进程结束....\n");
  //进入阻塞状态,等待子进程结束
 // pid_t res = wait(0);
  //printf("等到结束的子进程是%d\n",res);
  int result ;
  pid_t res = wait(&result);
  printf("等到结束的子进程是%d\n",res);
  printf("result=%d\n",result);
  if(WIFEXITED(result)){
    printf("子进程是正常结束的\n");
    //取返回值
    printf("子进程返回值:%d\n",WEXITSTATUS(result));
  }
  return 0;
}


九,waitpid------等待某个指定的子进程
waitpid.c
#include<stdio.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<unistd.h>
int main(){
  int pid1,pid2;
  pid1 = fork();
  if(pid1>0){
  pid2 = fork();
  }


  if(pid1 == 0){//子进程一
   printf("子进程一开始执行,睡眠3秒,pid=%d\n",getpid());
   sleep(3);
   printf("子进程一结束\n");
   exit(100);
  }
  if(pid2 == 0){
     printf("子进程二开始,pid=%d,睡1秒\n",getpid());
     sleep(1);
     printf("子进程二结束\n"); 
     exit(200);
  }
  //父进程
  printf("父进程等待子进程一结束\n");
  int result;
  waitpid(pid1,&result,0);
  if(WIFEXITED(result)){
     printf("子进程一的返回值:%d\n",WEXITSTATUS(result));
  }
  printf("父进程结束\n");
   return 0;
}
十,exec函数
在程序中调用另外一个程序
exec函数一旦执行,后面的代码都不会被执行了,因为全部被覆盖掉了


十一,system函数
相当于fork一个进程执行

















0 0