题目2009校园招聘NS试题(一) 一、编程题(30分) 现代的处理器提供了compare-and-swap原子操作:int compare_and_swap(int * pv, const int cv, const int nv);即比较*pv与cv,如果相等,则把*pv值替换为nv并返回*pv原值,否则返回*pv的值。请利用上述原子操作实现如下操作:int inc_if_gt_zero(int * pv);即如果*pv > 0,则把*pv加1并返回修改后的*pv,否则返回*pv。结果要线程安全且不使用锁、信号灯、互斥量、临界区或类似机制。 二、算法题(35分) 题目:假设有一台机器A,有1G内存,另外若干台机器(B、C、D……)通过网络TCP向机器A传输数据,A机器把接收到的数据写入硬盘。B、C、D等机器的数据按记录传输,每条记录大小范围:1M~16M。为了保证每条记录的原子性,B、C、D等机器每次先向A汇报数据量大小,然后再进行数据传输。汇报数据大小时,A机器会给记录分配一个序号,写入文件时每个记录按序号顺序、原子写入。B、C、D等机器处理速度和网络速度都不尽相同,因此汇报数据大小之后,记录数据传递到A的顺序可能不一定按分配好的序号顺序到达。现在要求给A上程序设计一个数据结构,利用该数据结构能高效的接收数据并顺序高效的写入磁盘(也即是不能序号大的记录先写,然后再回写序号小的记录;也不能接收到几十个字节就写一次磁盘)。 三、系统设计题(35分) 现有计算机的内存大部分为易失性内存,一旦断电内存中的数据就会全部丢失,所以操作系统的设计充分的考虑了易失性内存的特点。
问:如果在以后内存全部为非易失性内存,那么应该如何设计新的操作系统,或者说需要对现有的操作系统做哪些修改和改进? 

解决方案 »

  1.   

    int inc_if_gt_zero(int *pv)
    {
      for(; ;)
      {
       int r = *pv;
       if (r <=0) return r;
       if (r == compare_and_swap(pv, r, r+1))
         return r+1;
      }
    }
      

  2.   

    int inc_if_gt_zero(int * pv)
    {
        return compare_and_swap(pv, -(*pv), *pv) == 0 ? 0 : compare_and_swap(pv, abs(*pv), *pv + 1);
    }
      

  3.   

    #include <Windows.h>int *pv;
    int share = 1;//用cmpxchg实现CAS
    int compare_and_swap(int *pv,const int cv,const int nv)
    {
    int rv=*pv;
    __asm{
    mov eax,cv
    mov ecx,pv
    mov ebx,nv
    cmpxchg [ecx],ebx
    }
    return rv;
    }int inc_if_gt_zero(int *pv)
    {
        int ret = 0;
        int cv;
        int nv;
        while(1)
        {
           //执行一次,得到*pv的当前值,必须确保不修改pv的原始值
           //ret = compare_and_swap(pv,-1,-1);
           
           //直接取就可以
           ret = *pv;
           //如果该值小于等于0,可以安全的返回ret值
           if(ret<=0) return ret; 
           //否则需要对pv作加一的操作
           cv = ret;
           nv = ret+1;
           //ret = compare_and_swap(pv,cv,nv);
           //*pv = nv; //改为普通赋值速度会更快,但运行结果随机化
           *pv = *pv + 1;
           if(ret==cv) return ret+1;
        }
    }
    //工作线程,操作pv,要求:确保线程的运行是无序的
    DWORD WINAPI ThreadFun(LPVOID lpParam)
    {
      int id = (int)lpParam;
      int i;
      
      srand((unsigned)time(0));
        
      //打乱线程的第一次运行顺序
      for(i=0;i<5;i++)  Sleep(200*(1+rand()*5/RAND_MAX));
      for(i=0;i<20;i++)
      {
            Sleep(20*(1+rand()*2/RAND_MAX));
       printf("Thread %d NO. %d\n",id,i);
       Sleep(20*(1+rand()*2/RAND_MAX));
       inc_if_gt_zero(pv);//***************************  }
      printf("Thread %d returned\n",id);
      return 0;
    }//主函数测试
    //   开20个线程,每个线程对share通过inc_if_gt_zero加1操作20次
    //   share初值可以任意设置
    //   如果share<=0,值不变
    //   如果share>0,最终结果应该是: 初值+400
    int main(void)
    {  int i; srand((unsigned)time(0));

            pv = &share;
      
    for(i=0;i<20;i++) CreateThread(NULL,0,ThreadFun,(LPVOID)i,0,NULL);

    //主线程用原始方法等待所有线程终止
    getchar();
    printf("运行结果: share = %d\n",share);
    }