- 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 :删除共享内存