==================进程间的通信========================
回顾:
1。计时器
1。struct itimerval{ struct tiemval it_interval; // 间隔时间:间隔x时间发送一次信号 struct timeval xxx... ;//开始时间: x时间开始发信号}
2。精确的时间结构体
struct timeval{ long tv_sec; long tv_usec; } ****以后如果要用到准确的时间表示,这个东西就经常用到哦。
2。 可靠的信号:34--64 不可靠的信号: 1--32 中间有32 , 33 这些个空的信号不存在,就是起到分隔可靠与不可靠来的。
3。消息队列、信号量、共享内存 这3个东东 都使用的是:IPC结构。
上课:
一。共享内存段
1.shmctl(id,命令,取决于命令的一种结构体) 函数:用于控制共享内存段的函数。msgctl用于控制消息队列。
******几乎所有的重要的系统函数,是经常需要通过判断返回值是否为-1,来表示成功否。所以,几乎每次的函数调用之后,我们都需要判断一下 if (xxx == -1) ,这个是必须的,不可避免的。***
2。共享内存段有对应的一个结构体,这个结构体记录了该内存段的一些信息:权限,主人等等,我们不能够直接访问该struct,我们必须自己准备好一个相同的struct来通过赋值,复制的方式。方可查看到这个struct里面的东西。
3。shmctl(id,IPC_RMID,0) 删除共享存储段,并不会立马就删除。只是搞一个删除标记,因为也许其他的进程还在用这个内存段呢。所以不能立马就删除了。其他想要挂接的进程会挂接不上来。直到等到所有的进程都脱接了(解除印射了)才会真正的删除掉。
二。IPC命令: (这些东西都是由内核进行管理的,所以进程结束了之前需要申请删除,否则依旧存在,可以通过ipcs命令来查看到。)
显示功能:ipcs -a -m -q -s
删除功能:ipcrm -m -q -s ID
三。消息队列(同共享内存段差不多,但是他是用链表做成的队列:先进先出哦)
消息:即数据(不同类型的数据) ipcs -q
1。函数:msgget msgsnd msgrvc ... msgctl
步骤:1。确定key 2.创建/获取消息队列 3。发送和接收消息(会发送到内核管理的消息队列区域中去) 4。删除消息队列
2。消息队列的删除是与共享内存不一样的,他是立即删除,而非做个标记。所以程序员要注意:是否还有进程在用该消息队列
3。消息类型: 2类型(会取到第一个2类型的消息) -2类型(会取到<=(小于或者等于)2类型的消息)这就是为负数的意义。
===============下午:==========
一。消息类型:
msgrcv(id,&structdata,sizeof(structdata),1(类型),0(会等待,NOWAIT表示不等待))
接收和发送的消息,他们的大小要对应,这样才能够成功的接收掉(如果接收的大小小了,那么会被截断,丢弃)。 如果指定了类型,那么只有符合该类型的消息才可以被接收到消息对列里面去。0 则表示任意类型。
消息的格式必须是这样子的:struct msg { long mtype; // 必须 > 0 renyitype mydata;//任意的数据类型,结构体也可以的 };
二。信号量
概念:他是用来控制资源的访问,即多个进程公共的计数器。 他的删除,也是同消息队列一样,是立即删除。 设置一个信号量用serval 设置一个信号量集就用setall
-1 获取 +1 释放
三。多线程编程
1。区别:进程与线程区别
0。线程是进程的一部分,它有自己的独立的栈空间,类似于一个函数。
1。线程只占用进程的栈区,所以其他区与进程共享
2。一个进程中,main()是主线程,线程可以启动线程,主线程一旦结束,那么其他的线程也会结束。
3。线程会竞争cpu资源。
2。在cpu眼中,只有线程,没有进程。
3。-> 比 . 的访问效率要底,从生成的汇编代码我们可以看出来。 为了溺补这个缺陷,我们可以用restrict来提高一点效率。
4.所有有关线程的操作,都在libpthread.so库里面,所以,程序中用到了线程的东西,就要 gcc abc.c -l pthread 来引用这个库。
5。多线程的优点:消耗资源少,能处理多个任务。:例如:火车票,每一个请求就会启动一个线程来服务它。一个服务器给多个客户端服务。即多任务,多线程。