内容:
系统标识
时间与日期
多进程编程
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;
}