1.进程和线程的区别。
进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性。进程和线程的区别在于:
简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
线程的划分尺度小于进程,使得多线程程序的并发性高。
另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行.
2.如何保护process内threads之间的共享资源
mutex_init(&m, USYNC_PROCESS, 0); rwlock_init(&rw, USYNC_PROCESS, 0); cond_init(&cv, USYNC_PROCESS, 0); sema_init(&s, count, USYNC_PROCESS, 0);
锁
信号量
互斥量
->线程互斥
3.进程间通信的方法(至少写三种)
1. 剪贴板
2、WM_COPYDATA消息
3、DDE/DDEML
4、mailslot
5、管道 pipe
6、COM
7. 文件映射FileMapping
8. Socket
9. RPC
10. CreateEvent, Semaphore, Mutex , CreateMapFile, SendMessage
进程间通信,指的是进程间相互传递
信息或者数据而己!没有什么太神秘的!
一般情况下,每一个进程都有一个独立的空间虚拟空间,大家在自己的空间里自己玩自己的!但是他们都受制于WIN的管理,WIN就要在他们空间里放一些信息了,一放不要紧就放了2G(32位),进程只有用自己的2G 了,好可怜啊!但是这两G为我们提供了空间!
进程间能信,还有一个问题,就是进程间线程的同步问题!这个了在总结(:
总而言之,进程间通信主要用有:
剪切板
虚拟文件
邮草
管道
socket
每个进程有自己的地址空间。两个进程中的地址即使值相同,实际指向的位置也不同。进程间通信一般通过操作系统的公共区进行。
同一进程中的线程因属同一地址空间,可直接通信。
只有进程间需要通信,同一进程的线程share地址空间,没有通信的必要,但要做好同步/互斥mutex,保护共享的全局变量。线程拥有自己的栈。同步/互斥是原语primitives.而进程间通信无论是信号,管道pipe还是共享内存都是由操作系统保证的,是系统调用.
进程是一个具有独立功能的程序,他是关于某个数据集合的一次可以并发执行的运行活动。进程作为构成系统的基本细胞,不仅是系统内部独立运行的实体,而且是独立竞争资源的实体。
线程也被称为轻权进程,同一进程的线程共享全局变量和内存,使得线程之间共享数据很容易也很方便,但会带来某些共享数据的互斥问题。
许对程序为了提高效率也都是用了线程来编写。
父子进程的派生是非常昂贵的,而且父子进程的通讯需要ipc或者其他方法来实现,比较麻烦。而线程的创建就花费少得多,并且同一进程内的线程共享全局存储区,所以通讯方便。
线程的缺点也是由它的优点造成的,主要是同步,异步和互斥的问题,值得在使用的时候小心设计。
4.宏定义和typedef有何区别
宏定义可以设置参数,虽然只是参数替换.但typedef不可以.
5.写一个宏MIN,得到两个数值a和b的较小的一个。
#define MIN(A,B) ((A) <= (B) ? (A) : (B))
6.《C/C++高质量编程》里面的几个写出sizeof(…)等于多少的几个题目
某32位系统下, C++程序,请计算sizeof 的值.
char str[] = “hello”
char *p = str ;
int n = 10;
请计算
sizeof (str ) = ?(1)
sizeof ( p ) = ?(2)
sizeof ( n ) = ?(3)
void Foo ( char str[100]){
请计算
sizeof( str ) = ?(4)
}
void *p = malloc( 100 );
请计算
sizeof ( p ) = ?(5)
答:(1)6 (2)4 (3) 4 (4)4 (5)4
记住所有的指针都为一个机器长度4字节
7.《C/C++高质量编程》里面的几个GetMomery(…)、写出函数输出结果等关于分配内存的题目
(1)
void GetMemory(char *p)
//试图用指针参数申请动态内存 ,这是传值的方式
//如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”,见(2)
{
char *s=NULL;
s= (char*)malloc(100*sizeof(char));
p=s;
//p为行参先指向str.然而p = (char *)malloc(100);会将p转移指向另一块
//申请的内存而未将str也指向它.所以在strcpy时str仍为null,导致崩溃
}
void main()
{
char *str = NULL;
GetMemory(str);
strcpy(str,”hello world”); // 运行错误
printf(“%s\n”,str);
}
请问运行Test 函数会有什么样的结果?
答:程序崩溃, str作为实参,通过传值方式并没有分配到内存,strcpy给一个空指针导致溢出.
(2).
Void GetMemory(char **p, int num){
*p = (char *)malloc(num);
//而所有malloc出的内存必须要通过手动free掉.所以会有内存泄漏
}
void main(){
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, “hello”);
printf(str);
}
请问运行函数会有什么样的结果?
答:输出“hello”, 内存泄漏
原因:其中char** 为指向指针的指针,
*p=s;//修改指针所指存储单元的值,
GetMemory(&str); //注意,此处传递指针的地址
str赋值成功,输出hello
(3)
void Test(void){
char *str = (char *) malloc(100);
strcpy(str, “hello”);
free(str);
if(str != NULL){
strcpy(str, “world”);
printf(str);
}
}
请问运行Test 函数会有什么样的结果?
答:篡改动态内存区的内容,后果难以预料,非常危险。
因为free(str);之后,str成为野指针,
if(str != NULL)语句不起作用。
说的简单一些,就是只收回内存,没有用str=NULL收回指针(4).
char *GetMemory(void){
char p[] = “hello world”;
return p;
}
void main(){
char *str = NULL;
str = GetMemory();
printf(str);
}
请问运行函数会有什么样的结果?
答:无效的指针,输出不确定,可能是乱码
原因:
// return语句返回指向“栈内存”的指针, 局部变量在栈中被分配,他的生存期就// 在函数内, 函数执行完后就释放了!
// 该指针的地址不是NULL,但其原现的内容已经被清除,新内容不可知。
在这种情况下:
char p[] = ”Hello world”;
你声明了一个栈上的数组,这个数组用 ”Hello world” 初始化。也就是说,C++(C也是这样),会在编译的时候把这个语句视为:
char p[11];
p[0] = ’H';
p[1] = ’e';
p[2] = ’l';
… …
p[10] = ’d';
请注意,大概没有哪个编译器会生成这样低效的代码,但从逻辑上说就是这样的——p这个数组在栈上,在函数返回的时候被弹出栈,其中的值不可预知!另一个要命的问题:即使你十分幸运,其中的值没有改变,但数组是没有’\0′结束符的,打印时仍会出问题。
// 可以改为char *p = “hello world”;
在这种情况下:
char *p = ”Hello world”;
这对于编译器来说,相当于:
__asm {
; char *p = ”Hello world”;
msg db ’Hello world’ 0 ; 直接分配在代码段中!
push msg ; 这个就是你的 p 指针了
… …
; return p;
pop eax
ret
}
不好意思,只好用伪造的汇编来说明一下……
常量 ’Hello world’ 分配在代码段中(注意,这只是可能的一种实现,事实上现代的编译器一般都不这么做,通常将它放在静态数据段中),所以,除非程序退出,”Hello world”始终存在!最后,在程序返回的时候,指针 p 作为栈变量被释放(pop),但其值却由eax 寄存器传回,这个值仍然指向”Hello world”,所以这种写法是正确的。
令人高兴的是,作为一个字面常量的字符串,它恰好有一个’\0′作为结束,没有任何问题! :)
总结:
几道题目都是很不错的题目,说到底也就是传值和传地址的问题。传值和传地址的问题从一开始学C就知道,可是要真的完全理解这个问题,好像并不是那么容易。
象这一个:
char *GetMemory(void)
{
char p[] = ”hello world”;
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}
虽然地址是传回去了,str的值也的确是等于p的,可是地址里面的内容却已经被释放了。所以打印出来的东西是一堆垃圾。
void GetMemory(char *p)
{
p = (char *)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);
strcpy(str, ”hello world”);
printf(str);
}
这个其实就是很典型的传值问题了。str实参,p形参,两者只是值相等,却没有什么关系。故虽然p分配了空间,可str还是str没有变化。故程序会崩溃。
void GetMemory2(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, ”hello”);
printf(str);
}
这个就是传地址了,所以会产生影响。故能够达到结果,不过分配了内存没有释放,于是就产生了内存泄漏了。
Related posts:




网站做的很不错,已经收藏下来了。
写得很不错