1. 可重入是什么概念?
可重入代码(Reentry code)也叫纯代码(Pure code)是一种允许多个进程同时访问的代码。为了使各进程所执行的代码完全相同,故不允许任何进程对其进行修改。程序在运行过程中可以被打断,并由开始处再次执行,并且在合理的范围内(多次重入,而不造成堆栈溢出等其他问题),程序可以在被打断处继续执行,且执行结果不受影响。
(不应该有全局变量或静态变量,因为这些变量会保存某一个进程的修改。可重入代码中的变量应该都是局部变量,每次重新调用时变量重新被赋值,从而保证,每个进程对它的访问都产生同样的结果。)
2. 如何确保代码可重入?
有名管道 (namedpipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
信号量(semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
消息队列( messagequeue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
信号 (sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
共享内存(shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
套接字(socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
1.全局变量 注:定义全局变量时最好使用volatile来定义,以防编译器对此变量进行优化。
2.Message消息机制,常用的Message通信的接口主要有两个:PostMessage为线程向主窗口发送消息。而PostThreadMessage是任意两个线程之间的通信接口。
3.CEvent对象,是MFC中的一个对象,可以通过对CEvent的触发状态进行改变,从而实现线程间的通信和同步。
互斥锁提供了以排他方式防止数据结构被并发修改的方法。
读写锁允许多个线程同时读共享数据,而对写操作是互斥的。
条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。
信号量机制(Semaphore):包括无名线程信号量和命名线程信号量
信号机制(Signal):类似进程间的信号处理
线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。
intsquare(volatileint*ptr)
{
return
*ptr**ptr;
}
1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。
(本地化数据和代码范围的好处和重要性)
extern和static完全不同,static会定义一个变量,extern不能定义一个变量,extern表示的是“已经存在一个变量,但是不在当前的编译单元内,需要在其他编译单元中寻找。
static int i; //只在a文件中用
int j; //在工程里用
static void init(){} //只在a文件中用
void callme() //在工程中用
{static int sum;}
上面的全局 i 变量和 init() 函数只能用在a.c文件中,全局变量sum的作用域只在callme里。
变量j和函数callme()的全局限扩充到整个工程文件。
所以可以在下面的b.c中用extern关键字调用。extern告诉编译器这个变量或者函数在其他文件里已经被定义了。
extern int j; //调用a文件里的
extern void callme(); //调用a文件里的
int main(){}
extern的另外用法是当C和C++混合编程时如果c++调用的是c源文件定义的函数或者变量,那么要加extern来告诉编译器用c方式命名函数:
extern "C" //在c++文件里调用c文件中的变量
{ int j; void callme(); }
int main()
{ callme(); }
find -name "$(date +%F)*" -exec mv {} ./history \;发现当前目录下有用当天日期为文件名的文件,即做MV
int main(){ fstream _file; _file.open(FILENAME,ios::in);
else { cout<<FILENAME<<"已经存在";} return 0; }
void main( void ) { if( (_access( "ACCESS.C", 0 )) != -1 ) { printf( "File ACCESS.C exists " );