随笔三

1、共享内存,管道,文件,socket传输的优缺点
管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身
linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数);
报文(Message)队列(消息队列):消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。能够进行数据传输的IPC,主要有如下几种:套接字(以下简称Socket)、共享内存、管道、文件。

其中Socket是我强烈推荐的IPC方式,理由如下:使用Socket可以天然地支持分布式部署;使用Socket可以比较容易地实现多种编程语言的混合(比如C++、Java、Python、Flex都支持Socket); 使用Socket还可以省掉了一大坨“锁操作”的代码。当两个进程在本机上进行Socket通讯时, 由于可以使用localhost环回地址,数据不用经过物理网卡,操作系统内核还可以进行某些优化。 这种情况下,Socket相对其它几种IPC机制,不会有太大的性能偏差.

2、视图
视图的定义: 
视图是一个虚表,它可以访问来自一个或多个表的列的子集.它是作为数据库中对象存储的一种询问.因此,视图是从一个或多个表中派生出数据的对象.这些派生出数据的表被称为基表或低层表.
视图提供一种安全机制.它保证用户只能检索和修改他们看到到的数据.基表中其余的数据既不能看到也不能被存取.复杂询问的使用也可以通过视图来简化.复杂询问可以以视图的形式存储,视图中的数据可使用简单询问来抽取.
定义视图后,它可以像数据库中任何其他的表一样被引用.虽然视图和表相似,但它并没有存储在 数据库中.它从基表中派生出它的值的集合.
视图的优点:
视图提供以下几个优点:
 (1):为用户提供相关的数据
 (2):隐藏数据的复杂性
 (3):从异构源组织数据
 (4):减少对象大小

3、static成员函数和普通的成员函数有什么不同点?

静态成员函数不能是虚函数;普通的成员函数可以是虚函数。
用static声明的局部变量,必须初始化,并且以后不能被再次赋值,每次函数调用时静态局部变量保留上次的值.
用static声明的函数表示只在本文件有效;

类的静态数据成员是属于类的,不属于任何对象,使用前必须初始化;
类的静态成员函数不与任何对象相联系,它可以直接访问类的静态数据成员,而不能直接访问类的
普通数据成员(即非静态数据成员),因为普通数据成员只有类的对象存在时才有意义。

关于静态成员函数,可以总结为以下几点:
1.静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数; 
2.非静态成员函数可以任意地访问静态成员函数和静态数据成员; 
3.静态成员函数不能访问非静态成员函数和非静态数据成员; 
4.由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长; 
5.调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,也可以直接使
用如下格式: <类名>::<静态成员函数名>(<参数表>)

4、虚函数须注意:
   1:只有类的成员函数才能说明为虚函数; 
   2:静态成员函数不能是虚函数; 
   3:内联函数不能为虚函数; 
   4:构造函数不能是虚函数; 
   5:析构函数可以是虚函数,而且通常声明为虚函数。

5、   何时使用多线程?
线程主要应用于四个主要领域
1、   offloading time-consuming task。由辅助线程来执行耗时计算,而使GUI有更好的反应。我想这应该是我们考虑使用线程最多的一种情况吧。
2、   Scalability。服务器软件最常考虑的问题,在程序中产生多个线程,每个线程做一份小的工作,使每个CPU都忙碌,使CPU(一般是多个)有最佳的使用率,达到负载的均衡,这比较复杂,我想以后再讨论这个问题。
3、   Fair-share resource allocation。当你向一个负荷沉重的服务器发出请求,多少时间才能获得服务。一个服务器不能同时为太多的请求服务,必须有一个请求的最大个数,而且有时候对某些请求要优先处理,这是线程优先级干的活了。
4、   Simulations。线程用于仿真测试。


6、   进程间同步和线程间同步?
进程线程同步互斥的控制机制,其实是由最原始最基本的4种方法实现的:
      1临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。 
  2互斥量:为协调共同对一个共享资源的单独访问而设计的。 
  3信号量:为控制一个具有有限数量用户资源而设计。 
  4事件:用来通知线程有一些事件已发生,从而启动后继任务的开始。

3、   线程之间如何通讯?
临界区(Critical Section) 
  保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。
互斥量(Mutex) 
  互斥量跟临界区很相似,只有拥有互斥对象的线程才具有访问资源的权限,由于互斥对象只有一个,因此就决定了任何情况下此共享资源都不会同时被多个线程所访问。当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其他线程在获得后得以访问资源。互斥量比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。
信号量(Semaphores) 
  信号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源,这与操作系统中的PV操作相同。它指出了同时访问共享资源的线程最大数目。它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。在用CreateSemaphore()创建信号量时即要同时指出允许的最大资源计数和当前可用资源计数。
   P操作申请资源:
    (1)S减1;
    (2)若S减1后仍大于等于零,则进程继续执行;
    (3)若S减1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,然后转入进程调度。 
  V操作 释放资源:
    (1)S加1;
    (2)若相加结果大于零,则进程继续执行;
    (3)若相加结果小于等于零,则从该信号的等待队列中唤醒一个等待进程,然后再返回原进程继续执行或转入进程调度。
事件(Event) 
  事件对象也可以通过通知操作的方式来保持线程的同步。并且可以实现不同进程中的线程同步操作。

7、   线程之间如何通讯?
线程常常要将数据传递给另外一个线程。通过PostThreadMessage(),可以将消息传递给目标线程,当然目标线程必须有消息队列。以消息当作通讯方式,比起标准技术如使用全局变量等,有很大的好处。如果对象是同一进程中的线程,可以发送自定义消息,传递数据给目标线程,如果是线程在不同的进程中,就涉及进程之间的通讯了。

8、进程之间的通讯:
IPC:管道、共享内存、消息队列、信号、信号量、套接字
共享内存(Shared Memory)。使用共享内存要做的是:设定一块内存共享区域;使用共享内存;同步处理共享内存。
第一步:设定一块内存共享区域。首先,CreateFileMapping()产生一个file-mapping核心对象,并指定共享区域的大小。MapViewOfFile()获得一个指针指向可用的内存。如果是C/S模式,由Server端来产生file-mapping,那么Client端使用OpenFileMapping(),然后调用MapViewOfFile()。
第二步:使用共享内存。共享内存指针的使用是一件比较麻烦的事,我们需要借助_based属性,允许指针被定义为从某一点开始起算的32位偏移值。
第三步:清理。UnmapViewOfFile()交出由MapViewOfFile()获得的指针,CloseHandle()交出file-mapping核心对象的handle。
第四步:同步处理。可以借助Mutex来进行同步处理。

9、动态链接库和静态链接库的区别?

静态链接库与动态链接库都是共享代码的方式,如果采用静态链接库,则无论你愿不愿意,lib中的指令都被直接包含在最终生成的EXE文件中了。但是若使用DLL,该DLL不必被包含在最终EXE文件中,EXE文件执行时可以“动态”地引用和卸载这个与EXE独立的DLL文件。静态链接库和动态链接库的另外一个区别在于静态链接库中不能再包含其他的动态链接库或者静态库,而在动态链接库中还可以再包含其他的动态或静态链接库。

10、动态链接库的分类

1. Load-time Dynamic Linking 载入时动态链接
这种用法的前提是在编译之前已经明确知道要调用DLL中的哪几个函数,编译时在目标文件中只保留必要的链接信息,而不含DLL函数的代码;当程序执行时,利用链接信息加载DLL函数代码并在内存中将其链接入调用程序的执行空间中,其主要目的是便于代码共享。
2. Run-time Dynamic Linking 运行时动态链接
这种方式是指在编译之前并不知道将会调用哪些DLL函数,完全是在运行过程中根据需要决定应调用哪个函数,并用LoadLibrary和GetProcAddress动态获得DLL函数的入口地址。

11、哪些函数不能为虚函数

普通函数(非成员函数);静态成员函数;内联成员函数;构造函数;友元函数。
一、普通函数(非成员函数)只能被overload,不能被override,声明为虚函数也没有什么意思,因此编译器会在编译时邦定函数。
二、构造函数不为虚函数,构造函数本来就是为了明确初始化对象成员才产生的,然而virtual function主要是为了再不完全了解细节的情况下也能正确处理对象。另外,virtual函数是在不同类型的对象产生不同的动作,现在对象还没有产生,如何使用virtual函数来完成你想完成的动作。
三、内联函数就是为了在代码中直接展开,减少函数调用花费的代价,虚函数是为了在继承后对象能够准确的执行自己的动作,这是不可能统一的。(inline函数在编译时被展开,虚函数在运行时才能动态的邦定函数)
四、静态成员函数对于每个类来说只有一份代码,所有的对象都共享这一份代码,他不归某个具体对象所有,所以他也没有要动态邦定的必要性。
五、因为C++不支持友元函数的继承,对于没有继承特性的函数没有虚函数的说法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值