I/O进程3
- day3 
- 五、进程 
- 7.函数接口 
- 7.1创建子进程 
- pid_t fork(void);
 - 功能:创建子进程
 - 返回值:成功:在父进程中:返回子进程的进程号 >0  在子进程中:返回值为0;  失败:-1并设置errno  
 - 特点 
- 1.子进程几乎拷贝了父进程的所有内容,包括代码、数据,缓冲区,系统数据段中的值,栈中的数据,父进程打开的文件,但是PID,PPID不同
 - 2.fork之前的代码会被复制但是不会被重新执行,fork之后的代码会被复制,并且父子进程分别执行一遍。
 - 3.父子进程的空间相互独立,互不影响,当在相应的进程中改变全局变量,静态变量,都互不影响
 - 4.fork之前打开的文件,fork之后拿到的是同一个文件描述符,操作的是同一个文件指针
 - 5.若父进程先结束,子进程成为孤儿进程,被init进程所收养,会变成后台进程。
 - 6.若子进程先结束,父进程不结束,父进程没有及时回收,子进程就会变成僵尸进程(避免僵尸进程的产生)
 
  
  
  - 8.回收进程 
- pid_t wait(int *status);
 - 功能:回收子进程资源(阻塞)
 - 参数:status:子进程退出状态,不接受子进程状态设为NULL
 - 返回值:成功:回收的子进程的进程号       失败:-1                                                                          
 - pid_t waitpid(pid_t pid, int *status, int options);
 - 功能:回收子进程资源
 - 参数:
 - pid:>0 指定子进程进程号        =-1 任意子进程        =0 等待其组ID等于调用进程的组ID的任一子进程          <-1 等待其组ID等于pid的绝对值的任一子进程    
 - status:子进程退出状态    
 - options:0:阻塞          WNOHANG:非阻塞
 - 返回值:正常:结束的子进程的进程号      当使用选项WNOHANG且没有子进程结束时:0       出错:-1  
 
  - 9.结束进程 
- void exit(int status);
 - 功能:结束进程,刷新缓存
 - 参数:退出的状态 不返回。  
 
  - 10.获取进程号 
- pid_t getpid(void);
 - 功能:获取当前进程的进程号
 - pid_t getppid(void);
 - 功能:获取当前进程的父进程号  
 
  
  - 六、进程间通信 
- 1.为什么要进行进程间通信  
 - 2.进程间通信方式(7) 
- (1).早期进程间通信 无名管道(pipe)、有名管道(fifo)、信号(sem)
 - (2).system V IPC通信 共享内存(share memory)、消息队列(message queue)、信号灯集(semaphore)
 - (3).BSD: 套接字(socket)
 
  - 3.无名管道 
- 3.1原理图 
-  

  - 通信原理:一个进程的输出可以当作另一进程的输入
 
  - 3.2特点 
- (1).只能用于具有亲缘关系的进程间通信
 - (2).半双工通信模式,具有固定的读端和写端 {单工:只能单方向通信, 广播 半双工:可以双向通信,但是同一时间不可以 对讲机 全双工:可以双向同时通信 打电话}
 - (3).无名管道可以被看做一个特殊的文件,对于他的读写可以使用文件IO函数 (注意:不是文件,他只是存在于内核空间的一部分,无实际文件)
 - (4).管道基于文件描述符进行通信。当一个管道建立的时候,它会自动创建两个文件描述符,一个用于读fd[0],一个用于写fd[1]。
 
  - 3.3函数 
- int pipe(int fd[2])
 - 功能:创建无名管道
 - 参数:文件描述符 fd[0]:读端 fd[1]:写端
 - 返回值:成功 0       失败 -1
 
  
  - 4.有名管道(FIFO) 
- 4.1特点 
- (1).可以使互不相干的两个进程通信
 - (2).有名管道可以通过路径名来指出,并在文件系统中可见,但是内容存储在内存中
 - (3).进程通过文件IO操作有名管道
 - (4).有名管道遵循先进先出的原则,不支持lseek()操作
 - (5).半双工通信
 
  - 4.2函数 
- int mkfifo(const char *filename,mode_t mode);
 - 功能:创建有名管道
 - 参数:filename:有名管道文件名        mode:权限
 - 返回值:成功:0        失败:-1,并设置errno号
 
  
  
  - 七、信号 
- 1.例子 
- kill -l:查看系统中信号
 - kill -num pid:给pid进程发送pid信号
 
  - 2.概念 
- (1).信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式。 (2).信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。 (3).如果该进程当前并未处于执行态,则该信号就由内核保存起来,直到该进程恢复执行再传递给它;如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞被取消时才被传递给进程。
 
  - 3.信号响应方式 
- (1.)忽略信号:对信号不做任何处理,但是有两个信号不能做忽略处理:SIGKILL和SIGSTOP
 - (2).捕捉信号:定义信号处理函数,当信号发生的时候,执行相应的处理函数,但是有两个信号不能做捕捉处理:SIGKILL和SIGSTOP
 - (3).执行缺省操作:linux对每种信号都规定了默认信号。
 
  - 4.信号的种类 
- 2)SIGINT:结束进程,对应快捷方式ctrl+c
 - 3)SIGQUIT:退出信号,对应快捷方式ctrl+\
 - 9)SIGKILL:结束进程,不能被忽略不能被捕捉
 - 14)SIGALRM:闹钟信号,alarm函数设置定时,当到设定的时间时,内核会向进程发送此信号结束进程。
 - 15)SIGTERM:结束终端进程,kill 使用时不加数字默认是此信号
 - 17)SIGCHLD:子进程状态改变时给父进程发的信号
 - 19)SIGSTOP:暂停进程,不能被忽略不能被捕捉
 - 20)SIGTSTP:暂停信号,对应快捷方式ctrl+z
 - 信号的种类
 - 在Linux中,信号被分为不可靠信号和可靠信号,一共64种,可以通过kill -l命令来查看
 - ●不可靠信号:也称为非实时信号,不支持排队,信号可能会丢失,比如发送多次相同的信号,进程只能收到一次,信号值取值区间为1~31
 - ●可靠信号:也称为实时信号,支持排队,信号不会丢失,发多少次,就可以收到多少次,信号值取值区间为32~64 信号产生的方式有如下几种:
 - ● 对于前台进程,用户可以输入特殊终端字符来发送,比如输入Ctrl+C
 - ● 系统异常,比如浮点异常和非法内存段访问
 - ● 系统状态变化,比如alarm定时器到期时将引起SIGALRM信号
 - ● 在终端运行kill命令或在程序中调用kill函数
 
  - 5.函数接口 
- 5.1发送信号 
- int kill(pid_t pid, int sig);
 - 功能:信号发送
 - 参数:pid:指定进程           sig:要发送的信号
 - 返回值:成功 0              失败 -1     
 -                                              
 -  int raise(int sig);
 - 功能:进程向自己发送信号
 - 参数:sig:信号
 - 返回值:成功 0              
 - 失败 -1                                                 
 -   int pause(void);
 - 功能:用于将调用进程挂起,直到收到信号为止。   
 
  - 5.2定时器 
- unsigned int alarm(unsigned int seconds)
 - 功能:在进程中设置一个定时器
 - 参数:seconds:定时时间,单位为秒
 - 返回值:如果调用此alarm()前,进程中已经设置了闹钟时间,则 返回上一个闹钟时间的剩余时间,否则返回0。
 - 注意:一个进程只能有一个闹钟时间。如果在调用alarm时 已设置过闹钟时间,则之前的闹钟时间被新值所代替  
 
  - 5.3信号处理 
- #include <signal.h>
 - typedef void (*sighandler_t)(int);
 - sighandler_t signal(int signum, sighandler_t handler);
 - 功能:信号处理函数
 - 参数:
 - signum:要处理的信号          
 - handler:信号处理方式              
 - SIG_IGN:忽略信号              
 - SIG_DFL:执行默认操作              
 - handler:捕捉信号 void handler(int sig){} //函数名可以自定义
 - 返回值:成功:设置之前的信号处理方式              失败:-1  
 
  
  
  - 八、共享内存 
- 1.特点 
- (1).共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,不需要进行任何数据的拷贝
 - (2).为了在多个进程间进行数据的交互,内核专门留了一块内存区,可以由需要访问的进程将其映射到自己的地址空间
 - (3).由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等
 
  - 2.编程步骤 
- (1).创建或者打开共享内存shmget
 - (2).映射共享内存到自己的用户空间shmat
 - (3).使用共享内存
 - (4).撤销映射
 - (5).删除共享内存  
 
  - 3.函数接口 
- int shmget(key_t key, size_t size, int shmflg);
 - 功能:创建或打开共享内存
 - 参数:     key 键值     size 共享内存的大小     shmflg IPC_CREAT|IPC_EXCL(判错)|0666
 - 返回值:成功 shmid              出错 -1  
 - void *shmat(int shmid,const void *shmaddr,int shmflg);
 - 功能:映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问
 - 参数:    
 - shmid 共享内存的id号    
 - shmaddr 一般为NULL,表示由系统自动完成映射,如果不为NULL,那么由用户指定    
 - shmflg:SHM_RDONLY就是对该共享内存只进行读操作  ,0 可读可写
 - 返回值:成功:完成映射后的地址,       失败:-1的地址
 - 用法:if((p = (char *)shmat(shmid,NULL,0)) == (char *)-1)                 
 -  int shmdt(const void *shmaddr);
 - 功能:取消映射
 - 参数:要取消的地址
 - 返回值:成功0       失败的-1                                                                                             
 - int shmctl(int shmid,int cmd,struct shmid_ds *buf);
 - 功能:(删除共享内存),对共享内存进行各种操作
 - 参数:    
 - shmid 共享内存的id号    
 - cmd IPC_STAT 获得shmid属性信息,存放在第三参数            
 - IPC_SET 设置shmid属性信息,要设置的属性放在第三参数            
 - IPC_RMID:删除共享内存,此时第三个参数为NULL即可
 - 返回:成功0      失败-1
 - 用法:shmctl(shmid,IPC_RMID,NULL);  
 
  - 4.命令 
- ipcs -m:查看系统中共享内存
 - ipcrm -m shmid :删除共享内存
 
  
  
  
 
 
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/900583.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!