unix_c++学习笔记2


内容:
系统标识
时间与日期
多进程编程

1. 系统标识符
    a.获得有关的系统信息
       #include<sys/types.h>
       int uname( struct utsname * name);// 用 man uname 查看 struct utsname
    b.获得系统的名称
       #include<unistd.h>
       int gethostname( char* name, int namelen ); // 成功返回 0, 否则返回 1
       例子:
       [code]
       #include<iostream>
  #include<unistd.h>
  #include<sys/utsname.h>
  
  using namespace std;
  
  int main(){
   cout<<"-------------- hostname ------------"<<endl;
   char name[ 100 ];
   memset( name, 0x00, sizeof( name ) );
   gethostname( name, sizeof( name ) );
   cout<< name <<endl;
   
   cout<<"-------------- uname ----------------"<<endl;
   struct utsname nm;
   memset( &nm, 0x00, sizeof( nm ) );
   uname( &nm );
   cout<<"sysname ="<< nm.sysname <<endl;
   cout<<"nodename ="<< nm.nodename <<endl;
   cout<<"release ="<< nm.release <<endl;
   cout<<"version ="<< nm.version <<endl;
   cout<<"machine ="<< nm.machine <<endl;
   return 0;
  }
  [/code]
  
2. 时间与日期
    4种表示形式:(1)time_t 1970年至今的秒数               (2) struct tm 以结构表示
                          (3) char * 字符串                               (4) formated char*  自定义格式
    (1)-->(2) 转换有函数: localtime() // 本地时间            gmtime() // 格林威治时间
    (2)-->(1) 转换有函数: mktime()
    (1)-->(3) 转换有函数: ctime()
    (2)-->(3) 转换有函数: asctime()
    (2)-->(4) 转换有函数: strftime()
    例子:
    [code]
    #include<iostream>
 #include<time.h>
 using namespace std;
 
 int main(){
  // time() get kernel time
  cout<<"-----------time_t-----------"<<endl;
  time_t t=0;
  time( &t );
  cout<< t <<endl;
  
  // time_t --> struct tm, localtime(),gmtime()
  // man localtime to see the struct tm
  cout<<"-----------struct tm-----------"<<endl;
  struct tm *p=NULL; 
  p=localtime( &t ); 
  cout<<"year:"<< p->tm_year+1900 <<endl; // the number of years since 1900
  cout<<"month:"<< p->tm_mon+1 <<endl; // tm_mon ranges 0 to 11
  cout<<"day:"<< p->tm_mday <<endl;
  
  // struct tm --> time_t
  cout<<"-----------mktime-----------"<<endl;
  time_t t1;
  t1=mktime( p );
  cout<< t1 <<endl;
  
  // time_t --> char *
  cout<<"-----------ctime-----------"<<endl;
  cout<< ctime( &t ) <<endl;
  char ct[ 100 ];                        //如果想保持返回值应开辟新空间,不能直接定义指针保存
  memset( ct, 0x00, sizeof( ct ) ); //因为ctime的返回值总是在同一空间,下次调用ctime时就会被更改
  strcpy( ct, ctime( &t ) );
  cout<< ct <<endl;
  
  // struct tm --> char *
  cout<<"-----------asctime-----------"<<endl;
  cout<< asctime( p ) <<endl;
  
  // struct tm --> formated char*
  cout<<"-----------strftime-----------"<<endl;
  char ft[ 100 ];
  memset( ft, 0x00, sizeof( ft ) );
  strftime( ft, sizeof( ft ), "%Y-%m-%d %H:%M:%S", p );
  cout<< ft <<endl;
  return 0;
 }
 [/code]

3.system 函数
   #include<stdlib.h>
   int system( const char * string );
   执行string 所表示的命令,将产生一个新的进程,system为阻塞函数, 新的进程结束后才继续
   例子:
   [code]
   #include<iostream>
 #include<stdlib.h>
 using namespace std;
 
 int main(){
  cout<<"----------begin---------"<<endl;
  system("ls -l");
  cout<<"----------end-----------"<<endl;
  return 0;
 }
 
 // 一个简单的shell
 #include<iostream>
 #include<unistd.h>
 using namespace std;
 
 int main(){
  char cmd[ 100 ];
  memset( cmd, 0x00, sizeof( cmd ) );
  while( 1 ){
   cout<<"[irini@localhost]#";
   cin.getline( cmd,sizeof( cmd ) );
   if( strcmp( cmd,"bye" )==0 ) break;
   system( cmd );
  }
  return 0;
 }

 [/code]
 
4. atexit() 函数
   #include<stdlib.h>
   int atexit( void (*func) (void) );
   登记exit handler,最多可登记32个,在进程退出时最后登记的先调用,最先登记的最后调用
  
5. exit 与 _exit
    * 进程的退出过程:
    进程做的事: exit handler( atexit注册的), 关闭IO流,如果申请了堆空间就释放
    ------------------------------------------------------------------
    kernel做的事: 销毁进程空间, 删除进程表中的相应项
    *  exit 是正常退出,想做进程的,然后进入kernel处理
       _exit 是异常退出,直接进入kernel
   
    例子:
    [code]
    #include<iostream>
 #include<unistd.h>
 using namespace std;
 
 void fn1(){
  cout<<"in fn1()..."<<endl;
 }
 void fn2(){
  cout<<"in fn2()..."<<endl;
 }
 int main(){
  atexit( fn1 );
  atexit( fn2 );
  cout<<"return from main..."<<endl;
  //exit( 0 );
  _exit( 0 );
 }
 [/code]

 
6. 进程标识符
   #include<sys/types.h>
   #include<unistd.h>
   pid_t getpid(); // 当前进程号
   pid_t getppid(); // 得到父进程号
   例子:
   [code]
   #include<iostream>
 #include<sys/types.h>
 #include<unistd.h>
 using namespace std;
 
 int main(){
  cout<<"pid="<<getpid()<<endl;
  cout<<"ppid="<<getppid()<<endl;
  return 0;
 }
 [/code]


7. fork 函数
    * 创建一个新进程,这个进程是父进程的完全拷贝,完全拷贝父进程的进程空间,唯一的区别是fork()的返回值不同
      返回给父进程的是子进程的pid, 返回给子进程的是0        
     
      例子:
      [code]
      #include<iostream>
  #include<sys/types.h>
  #include<unistd.h>
  using namespace std;
  
  int main(){
   pid_t cid=fork();
   if( cid==0 ){
    for( int i=0; i<5; i++ ){
     cout<<"[child] pid="<<getpid()<<" ppid="<<getppid()<<endl;
     sleep( 1 );
    }
    exit( 0 );
   }else if( cid > 0 ){
    for( int i=0; i<5; i++ ){
     cout<<"[father] pid="<<getpid()<<" cid="<<cid<<endl;
     sleep( 1 );
    }
    exit( 0 );
   }else{
    cout<<"error"<<endl;
    exit( -1 );
   }
   return 0;
  }
  [/code]
  
   * fork后,父子进程相互独立,如果之前父进程申请了一个堆空间,那之后父子进程中的指针值相同吗?
     通过程序可验证他们是相同的,但指向的空间是不同,因为进程中分配给指针的不是绝对地址,
     是逻辑偏移地址,进程空间中正文段的起始地址是逻辑0
    
   * 如果父进程在子进程之前退出,子进程会被初始化进程(pid=1) 托管
     如果子进程在父进程之前退出,子进程不会被销毁,变为僵死进程 Z状态,等待父进程处理
    
     例子:
     [code]
     #include<iostream>
  #include<sys/types.h>
  #include<unistd.h>
  using namespace std;
  
  void fn(){
   cout<<"in fn()... "<<endl;
  }
  int main(){
   atexit( fn );
   pid_t cid=fork();
   if( cid==0 ){
    for( int i=0; i<5; i++ ){
     cout<<"[child] pid="<<getpid()<<endl;
     sleep( 1 );
    }
    exit( 0 );
   }else if( cid > 0 ){
    cout<<"father exit..."<<endl;
    exit( 0 );
   }else{
    cout<<"error"<<endl;
    exit( -1 );
   }
   return 0;
  }
  [/code]
  
8. wait 和 waitpid 函数
    处理结束的子进程,是阻塞函数
    #include<sys/types.h>
    #include<sys/wait.h>
    pid_t wait( int * statloc );
    pid_t waitpid( pid_t pid, int *static, int option );
    返回值为子进程的pid
    statloc 用于接受终止的子进程的返回状态
    option 通常设为0  
   
   
    例子:
    [code]
    #include<iostream>
 #include<sys/types.h>
 #include<sys/wait.h>
 #include<unistd.h>
 using namespace std;
 
 int main(){
  pid_t cid=fork();
  if( cid==0 ){
   sleep( 3 );
   cout<<"[child] pid="<<getpid()<<" ppid="<<getppid()<<endl;
   exit( 0 );
  }else if( cid > 0 ){
   cout<<"[father] pid="<<getpid()<<" cid="<<cid<<endl;
   int statloc=0;
   pid_t id=waitpid( cid, &statloc, 0 );
   cout<<"[child] "<< id <<" exited"<<endl;
   cout<<"exit value is "<< statloc <<endl;
   if( WIFEXITED( statloc ) )
    cout<<"value "<<WEXITSTATUS( statloc )<<endl;
   else  cout<<"signal "<<WTERMSIG( statloc )<<endl;
  }else{
   cout<<"error"<<endl;
   exit( -1 );
  }
  return 0;
 }
 [/code]
 
9. exec 函数
   类似system,建立新的进程,但不新建进程空间,而是把原进程空间清0变成自己的开始执行
   则原进程exec之后的代码不在存在,失效
  
   例子:
   [code]
   #include<iostream>
 #include<unistd.h>
 using namespace std;
 
 int main(){
  cout<<"-------------begin-----------"<<endl;
  //execlp( "ls","ls","-l","-a",NULL );   // 第一个参数为要执行的命令文件名,后面的为命令行参数(从0开始都要写,以NULL结束)
  char* argv[]={ "ls","-l","-a",NULL };
  execvp( "ls", argv );
  cout<<"-------------end-------------"<<endl;
  return 0;
 }
 
 
                  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值