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
例子:

#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;
}



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()
例子:

#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;
}



3.system 函数
#include<stdlib.h>
int system( const char * string );
执行string 所表示的命令,将产生一个新的进程,system为阻塞函数, 新的进程结束后才继续
例子:

#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;
}




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

例子:

#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 );
}




6. 进程标识符
#include<sys/types.h>
#include<unistd.h>
pid_t getpid(); // 当前进程号
pid_t getppid(); // 得到父进程号
例子:

#include<iostream>
#include<sys/types.h>
#include<unistd.h>
using namespace std;

int main(){
cout<<
"pid="<<getpid()<<endl;
cout<<
"ppid="<<getppid()<<endl;
return 0;
}




7. fork 函数
* 创建一个新进程,这个进程是父进程的完全拷贝,完全拷贝父进程的进程空间,唯一的区别是fork()的返回值不同
返回给父进程的是子进程的pid, 返回给子进程的是0

例子:

#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;
}



* fork后,父子进程相互独立,如果之前父进程申请了一个堆空间,那之后父子进程中的指针值相同吗?
通过程序可验证他们是相同的,但指向的空间是不同,因为进程中分配给指针的不是绝对地址,
是逻辑偏移地址,进程空间中正文段的起始地址是逻辑0

* 如果父进程在子进程之前退出,子进程会被初始化进程(pid=1) 托管
如果子进程在父进程之前退出,子进程不会被销毁,变为僵死进程 Z状态,等待父进程处理

例子:

#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;
}



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


例子:

#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;
}



9. exec 函数
类似system,建立新的进程,但不新建进程空间,而是把原进程空间清0变成自己的开始执行
则原进程exec之后的代码不在存在,失效

例子:

#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;
}



irini   2005-10-17 21:46:02 评论:0   阅读:682   引用:0

发表评论>>

署名发表(评论可管理,不必输入下面的姓名)

姓名:

主题:

内容: 最少15个,最长1000个字符

验证码: (如不清楚,请刷新)

Copyright@2008 powered by YuLog