进程知识点

来源:互联网 发布:南京烘焙培训班 知乎 编辑:程序博客网 时间:2024/05/31 13:14
 

进程:运行起来的程序(动态性,并发性,独立性,异步行)
三态:就绪---(调度)---执行---(条件不足)---阻塞---(读数据)读完又成就绪态
程序:静态的

进程互斥:硬件资源或者软件资源不能同时被两个进程同时使用就会产生互斥
临界资源:在进程互斥当中同一时刻只允许一个进程访问的资源
进程的同步:一组并发进程按一定的顺序执行的过程A--B--C
进程调度:按一定算法,从一组待执行的进程中选出一个来占有CPU(抢占式调度和非抢占式调度)
调度算法:先来先服务调度算法,短进程优先调度算法,高级优先级调度算法(不同系统中不同优先级特性),时间片算法(公平调度法)
死锁:多个资源因竞争资源形成一种僵局

获得ID
#include<sys/types.h>
#include<unistd.h>
pid_t getpid(void)//本次进程的ID
pid_t getppid(void)//获取父进程的ID

进程创建-fork();
pid_t fork(void)

fork()被调用一次,返回两次,可能有三个返回值
1,在父进程中,返回新创建的子进程的PID;
2,在子进程中,返回0;
3,如果出现错误,返回一个负值;

#include<sys/types.h>
#include<unistd.h>
int main(void)
{
 pid_t pid;
 int count=0;//数据空间,堆栈空间全部拷贝,代码段共享
 pid=fork();
 count++;
 printf("count=%d\n",count);
 return 0;
}

pid_t vfork();
fork:子进程拷贝父进程的数据段,父子进程的执行次序不确定
vfork:子进程与父进程共享数据段,子进程先运行,父进程后运行

exec函数族
exec不会创建新的进程,用被执行的程序替换它调用的函数


int execl(const char *path,const char*arg1,...)//可执行文件完整路径
execl.c
#include<unistd.h>
main()
{
 execl("/bin/ls","ls","-al","/etc/passwd",(char *)0);
}


int execlp(const char*path,const char *arg1,...)//可执行文件名

int execv(const char*path,char *const arg[])//把要执行的命令放在argv[]数组里了


int system(const char* string)

#include<stdlib.h>
void main()

 system("ls -a /etc/passwd");


进程等待
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int *status)


进程间通信原因:
1,数据传输
2,资源共享
3,通知事件
4,进程控制


linux进程发展:UNIX进程间通信--基于System V进程间通信----POSIX(Portable Operating System Interface)进程间通信
linux进程间通信方式
1,pipe无名管道(父子进程之间的通信)和FIFO有名管道(实质是文件)
管道:单项的,先入先出,写(尾部),读(头部)
创建无名管道:int pipe(int filedis[2]);filedis[0]读,filedis[1]写
关闭无名管道:close(pipe_fd[0]),close(pipe_fd[1]);
必须在系统调用fork()前调用pipe(),否则子进程将不会继承文件描述符

//父子进程之间的通信
#include<unistd.h>
#include<errno.h>
#include<sys.types.h>
#include<stdio.h>
#include<stdlib.h>

int main()
{
 int pipe_fd[2];
 pid_t pid;
 char buf_r[100];
 char *p_wbuf;
 int r_num;
 memset(buf_r,0,sizeof(buf_r));
 
 if(pipe(pipe_fd)<0)
 {
  printf("pipe creat error!\n");
  return -1;
 }
 
 if(pipe(pipe_fd)==0)
 {
  printf("\n");
  close(pipe_fd[1]);
  sleep(2);
  if(r_num=read(pipe_fd[0],buf_r,100)>0)
  {
   printf("%d numbers read from the pipe is %s\n",r_num,buf_r);
  }
  close(pipe_fd[0]);
  exit(0);
 }
 else if(pid_t>0)
 {
  close(pipe_fd[0]);
  if(write(pipe_fd[1],"hello",5)!=-1)
   printf("parent write1 hello!\n");
  if(write(pipe_fd[1],"pipe",5)!=-1)
   printf("parent write2 pipe!\n");
  close(pipe_fd[1]);
  sleep(3);
  waitpid(pid,NULL,0);
  exit(0);
 }
}

有名管道
#include<sys/types.h>
#include<sys/stat.h>
int mkfifo(const char * pathname,mode_t mode)

mode-->O_NONBLOCK:没使用管道没数据进程会阻塞,使用了管道没数据,立刻出错返回

#include<unistd.h>
#include<errno.h>
#include<sys.types.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define FIFO "/tmp/myfifo"

main(int argc,char ** argv)
{
 char buf_r[100];
 int fd;
 int nread;

 if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!EEXIST))
  printf("cannot creaat fifoserver\n");

 printf(preparing for reading bytes...\n);

 memset(buf_r,0,sizeof(buf_r));
 
 fd=open(FIFO,O_CREAT|O_NONBLOCK,0);
 if(fd==-1)
 {
  perror("open");
  exit(1); 
 }
 while(1)
 {
  memset(buf_r,0,sizeof(buf_r));
  
  if((nread=read(fd,buf_r,100))==-1)
  {
   if(errno=EAGAIN)
    printf("no data yet\n");
  }
  printf("read %s from FIFO\n",buf_r);
  sleep(1);
 }
 pause();
 
}


 

2,信号signal
产生信号的方式:
按键、硬件异常(除数为0、无效的存储访问)、进程kill函数给另一个进程发送信号、kill命令给进程返送信号
进行信号处理:忽略次信号(SIGKILL、SIGSTOP除外)、执行用户希望的动作、执行系统默认动作(大多数默认处理是终止该进程)

发送信号:kill(自己给自己发,也可以给别人发)、raise(只能给自己发)
int kill(pid_t pid,int signo)
int raise(int signo)

alarm(给自己发信号)SIGALRM
unsigned int alarm(unsigned seconds)//多少秒后给自己发信号

pause函数:使进程等待直到收到信号为止
int pause(void)
只有执行了一个信号处理函数后,挂起才结束

#include<signal.h>
void(*signal(int signo,void(*func)(int)))(int)
func:SIG_IGN(忽略此信号)、SIG_DFL(默认方式)、信号处理函数名(使用该函数处理)

typedef void(*sighandler_t)(int)
sighandler_t signal(int signum,sighandler_t handler)

 

#include<signal.h>
#include<stdio.h>
#include<stdlib.h>


void my_func(int sign_no)
{
 if(sign_no==SIGINT)
  printf("I have get SIGINT\n");
 else if(sign_no==SIGQUIT)
  printf("I have get SIGQUIT\n");
}

int main()
{
 printf("Waiting for signal SIGINT or SIGQUIT\n");
 
 signal(SIGINT,my_func);
 signal(SIGQUIT,my_func);

 pause();
 exit(0);
}
kill -s SIGQUIT 3687//发送信号

3,共享内存:被多个进程共享的一部分物理内存
步骤:创建共享内存:shmget
 int shmget(key_t key,int size,int shmflg)
 映射:shmat
 int shmat(int shmid,char *shmaddr,int flag)
 解除映射:int shmdt(char *shmaddr)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>

#define PERM S_IRUSR|S_IWUSR

int main(int argc,char **argv)
{
 int shmid;
 char *p_addr,*c_addr;

 if(argc!=2)
 {
  fprintf(stderr,"Usage:%s\n\a",argv[0]);
  exit(1);
 }
 if(shmid=shmget(IPC_PRIVATE,1024,PERM)==-1)
 {
  fprintf(stderr,"Creat Share Meemory Error:%s\n\a",strerror(errno));
  exit(1);

 }
 if(fork())
 {
  p_addr=shmat(shmid,0,0);
  memset(p_addr,'\0',1024);
  strncpy(p_addr,argv[1],1024);
  wait(NULL);
  exit(0);
 }
 else
 {
  sleep(1);
  c_addr=shmat(shmid,0,0);
  printf("Client get %s\n",c_sddr);
  exit(0);
 }
}
4,消息队列(消息的链表)

信号能够传送的西诺西辆有限,管道则只能传送无格式的字节流
POSIX消息队列以及系统V消息队列
随着内核持续,消失:内核重新启动、人工删除
键值:
#include<sys/types.h>
#include<sys/ipc.h>
key_t ftok(char *pathname,char proj)//返回文件名对应的键值

打开创建:
#include<sys/msg.h>
int msgget(key_t key,int msgflg)//key:IPC_PRIVATE
msgflg:IPC_CREAT:创建新的消息队列
 IPC_EXCL:要创建的消息队列已经存在,则返回错误
 IPC_NOWAIT:读写消息队列要求无法满足时,不阻塞

发送消息:
int msgsnd(int msqid,struct msgbuf * msggp,int msgsz,int msgflg)
//消息格式
struct msgbuf

 long mtype://消息类型>0
 char mtex[1];//消息数据的首地址

int msgrcv(int msqid,struct msgbuf *msgp,int msgsz,long msgtype,int msgflg)


#include<stdio.h>
#include<sys/types.h>
#include<sys/msg.h.h>
#include<unistd.h>

struct msg_buf{
 int mtype;
 char data[255];
}

int main(void)
{
 key_t key;
 int msgid;
 struct msg_buf msgbuf;
 
 key=ftok("/tmp/2",'a');//把想使用的文件名转化为键值
 printf("key=[%x]\n",key);
 msgid=msgget(key,IPC_CREAT|0666);
 
 if(msgid==-1){
  printf("create error\n");
  return -1;
 }
 msgbuf.mtype = getpid();
 strcpy(msgbuf.data,"test haha");
 ret=msgsnd(msgid,&magbuf,sizeof(msgbuf.data),IPC_NOWAIT);
 if(ret==-1){
  printf("send message error!\n");
  return -1;
 }
 memset(&msgbuf,0,sizeof(msgbuf));
 ret=msgrcv(msgid,&msgbuf,sizeof(msgbuf.data),getpid(),IPC_NOWAIT);
 if(ret==-1){
  printf("recive message error!\n");
  return -1;
 }
 printf("rcv msg=[%s]\n",msgbuf.data);
}


5,信号量(保护临界资源)
#include<sys/sem.h>
int  semget(key_t key,int nsems/*创建信号量的个数*/,int semflg)

int semop(int semid,struct sembuf *sops,unsigned nsops/*指向数组元素的个数*/)

struct senbuf{
unsigned short sem_num;
short sem_op;
short sem_flg:
}

//6,套接字(socket)


原创粉丝点击