------------------------------------------------------------------------------------
第二天; 多线程
------------------------------------------------------------------------------------
1. uname: 操作系统的名字;
函数: uname();
2. gethostname(char* name,int size);
用法:
name: 用于存放函数的返回值;
size: 指定name的大小
例子:
-------------------
#include <iostream>
using namespace std;
#include <unistd.h>
int main()
{
char name[256];
int res=gethostname(name,256);
if(res<0)
cout<<"Eoor"<<endl;
else
cout<<name<<endl;
return 0;
}
-------------------------
(2) 时间和日期函数
概述:与时间有关的函数: ctime, asctime, strftime,gmtime ,localtime;
1.
string
1.ctime()
例子:
----------------
#include <iostream>
using namespace std;
#include <unistd.h>
#include <time.h>
int main()
{
time_t t=time(NULL);
cout<<ctime(&t)<<endl; //Fri Jan 26 10:15:20 2007 标准时间
}
--------------
2. tm格式 的时间; localtime(tm格式的地址):
#include <iostream>
using namespace std;
#include <time.h>
#include <iomanip>
int main()
{
const char* w[7]={"日","一","二","三","四","五","六"};
struct tm* bt=NULL;
time_t t=time(NULL);
bt = localtime(&t); //返回TM格式的指针;
cout << bt->tm_year+1900 << "年" << bt->tm_mon+1 << "月" << bt->tm_mday
<< "日 星期" << w[bt->tm_wday] << " " << setfill('0') << setw(2) << bt->tm_hour
<< ":" << setw(2) << bt->tm_min << ":" << setw(2) << bt->tm_sec << endl;
return 0;
}
-------------
srtftime() 格式化时间:
例子:
#include <iostream>
using namespace std;
#include <time.h>
int main()
{
char str[256];
time_t t=time(NULL);
struct tm* p=localtime(&t);
strftime(str, 256, "%Y-%m-%d %H:%M:%S", p);
cout << str << endl;
return 0;
}
--------------
(3) 多进程
***复习全局对象****
1. void func(): 退出处理函数
#include <stdlib.h>
int atexit(): 登记函数 //最多32个
例子:
------------------------------------------
#include <iostream>
using namespace std;
#include <stdlib.h>
void func1()
{
cout<<"call func1()"<<endl;
}
void func2()
{
cout<<"call func2()"<<endl;
}
void func3()
{
cout<<"call func3()"<<endl;
}
void func4()
{
cout<<"call func4()"<<endl;
}
int main()
{
cout<<"start..."<<endl;
atexit(func1);
atexit(func2);
atexit(func3);
atexit(func4);
cout<<"Program do somethig!!"<<endl;
}
结果:
start...
Program do somethig!!
call func4()
call func3()
call func2()
call func1()
--------------------------------------------
2.
A.
B.
C.
D.
E.
#include <stdlib.h>
void exit(int status); //正常方式结束
#include <unistd.h>
void_exit(int status); //异常无条件退出. A,B,C 三步会忽略掉.
每个进程有独立的4G的工作空间. //虚拟空间4G 所以地址只对本进程有意义.
exit()
例子:
#include <iostream>
using namespace std;
#include <stdlib.h>
void func1()
{
cout << "call func1()" << endl;
}
void func2()
{
cout << "call func2()" << endl;
}
void func3()
{
cout << "call func3()" << endl;
}
void func()
{
cout << "start..." << endl;
exit(0);
cout << "program do something.../n";
}
int main()
{
atexit(func1);
atexit(func2);
atexit(func3);
func();
return 0;
}
结果:
start...
call func3()
call func2()
call func1()
-----------------------------------------------
void_exit();
#include <iostream>
using namespace std;
#include <stdlib.h>
void func1()
{
cout << "call func1()" << endl;
}
void func2()
{
cout << "call func2()" << endl;
}
void func3()
{
cout << "call func3()" << endl;
}
void func()
{
cout << "start..." << endl;
_exit(0);
cout << "program do something.../n";
}
int main()
{
atexit(func1);
atexit(func2);
atexit(func3);
func();
return 0;
}
结果:
start...
程序不会正常结束
---------------------------------------------------------------
4. #include <stdlib.h>
int system(cont* string); // 参数必需是c风格的字符串;
//成功: 新程序的结束状态.
--------------------------------------------------------------
进程/家谱:
ineted ->in.telnetd 200 ->init 1 //初始化进程好永远是1->
sched 0;//调度进程 开机的自举程序.
--------------------------------------
复习一下PS 命令:
ps -p 进程号 //根据进程号查进程信息.
ps -l //此进程的详悉信息.
ps -e //查找当前所有的正在运行的进程.
---------------------------------------------------------------
strncmp(第一个字符串,第二个字符串,要比几个字符(可选));
---------------------------------------------------------------
自己写的SHELL
#include <iostream>
using namespace std;
#include <stdlib.h>
#include <string>
int main()
{
cout << "welcome to czq shell/n";
string cmd;
for(;
{
cout << "czq> ";
getline(cin, cmd);
if( cmd=="bye" )
break;
system(cmd.c_str());
}
return 0;
}
-------------------------------------------------
要剔除不能进入子目录的BUG
---------------------------------------
#include <stdlib.h>
#include <string>
#include <sys/stat.h>
int main()
{
cout << "welcome to czq shell/n";
string cmd;
for(;
{
cout << "czq> ";
getline(cin, cmd);
if( cmd=="bye" )
break;
if(strncmp(cmd.c_str(),"cd ",3)==0)
chdir(cmd.c_str()+3);
else
system(cmd.c_str());
}
return 0;
}
-------------------------------------------------
父进程不能够找到子进程
------------------------------------------------
进程标识符:
sleep(10); //参数是秒数.
ps -l
getpid() //得到进程号
getppid() //得到父进程.
#include <iostream>
using namespace std;
#include <unistd.h>
int main()
{
cout << getpid()<< endl;
cout << getppid() << endl;
sleep(10);
return 0;
}
-------------------------------------------------
fork //分叉; 产生一个子进程.把一个进程复制出一个新的进程(子进程)来.
一次调用两次返回.在两个进程中都有返回.也就是修改任何一个不会修改一个.
在子进程中返回值是0 在父进程中返回值是子进程的ID;
例子:
-----------------------------------------------------------
#include <iostream>
using namespace std;
#include <unistd.h>
#include <sys/types.h>
int main()
{
cout << "before fork()" << endl;
pid_t oldid = getpid();
pid_t id=fork();
cout << "after fork()" << endl;
if( getpid()==oldid )
cout << "parent process" << endl;
else
cout << "child process" << endl;
if( id<0 )
cout << "error in fork().." << endl;
else if( id==0 )
cout << "child process.." << endl;
else
cout << "parent process.." << endl;
return 0;
}
结果:
before fork()
pid:12623
after fork()
parent process
parent process..
after fork()
child process
child process..
--------------------------------------------
fork() 之后父子进程同时执行.演示程序:
#include <iostream>
using namespace std;
#include <unistd.h>
#include <sys/types.h>
int main()
{
pid_t cid=fork();
if( cid<0 )
cout << "fork error!" << endl;
else if( cid==0 )
{
for( int i=0; i<10; i++ )
{
cout << "child " << getpid() << endl;
sleep(1);
}
}
else
{
for( int i=0; i<10; i++ )
{
cout << "parent " << getpid() << endl;
sleep(1);
}
}
return 0;
}
结果:
parent 13168
child 13169
child 13169
parent 13168
child 13169
parent 13168
child 13169
parent 13168
child 13169
parent 13168
parent 13168
.......
子进程和父进程同时执行;
----------------------------------------------------------
子进程和父进程是否同时结束?
答案: 不是
----------------------------------------------------------
孤儿进程: 一个进程的父进程先结束, init 进程会领养所有此进程.
init 孤儿院(呵呵)/
---------------------------------------------------------
一般子进程会现结束.
子进程结束,父进程还在,此进程就叫僵尸进程.
--------------------------------------------------------
回收子进程的进程ID;
pid_t wait() //返回回收的进程ID; 任意子进程;
pid waitpid(pid_t pid ,itn* stticoc,int option)//回收指定的子进程的资源. 返回子进程ID
option //正常的等待, 不等待 用WNOHANG 没有子进程等待返回0;
pid: 用-1 表示任意等待进程并且不等待.
僵尸进程会在父进程结束后回收僵尸进程.
因此要自己处理僵尸进程的问题.
-----------------------------------------------------------
解析子进程的返回状态:
#include <iostream>
using namespace std;
#include <sys/wait.h>
#include <unistd.h>
int main()
{
if( fork()==0 )//child process
{
cout << "child sleep..." << endl;
sleep(10);
cout << getpid() << " exit/n";
exit(100);
}
else//parent process
{
system("ps -l -u 295");
int stat;
cout << "wait child..." << endl;
pid_t cid = wait(&stat);
cout << "wait " << cid << endl;
cout << "stat=" << stat << endl;
if( WIFEXITED(stat) )
cout << "exit code:" << WEXITSTATUS(stat) << endl;
else
cout << "abnormally!" << endl;
system("ps -l -u 295");
}
return 0;
}
}
结果:
child sleep...
17897 exit
wait 17897
25600
exit code:100
------------------------------------------------
回收子进程资源
#include <iostream>
using namespace std;
#include <sys/wait.h>
#include <unistd.h>
int main()
{
if( fork()==0 )//child
{
cout << "child " << getpid()<<endl;
sleep(5);
return 123;
}
int stat;
pid_t cid=waitpid(-1, &stat, 0);
cout << "waitpid " << cid << endl;
if( WIFEXITED(stat) )
cout << WEXITSTATUS(stat) << endl;
else
cout << "abnomal!" << endl;
return 0;
}
------------------------------------------------------------
父子进程在一起不好-乱-所以把父子进程的代码分开;
executive CEO
---------------------------------------------------
exec()
谁调用这个函数,就装入一个新程序,用新程序的代码覆盖旧程序代码,之后,新程序从头开始执行,所以在EXEC()后面的代码就不执行.
一系列函数
1. execcl() : //参数格式不变.不会使用PATH .要完整(绝对)路径.否则会执行失败
2. execcv(); //可以传递环境变量.
3. execcle() //
4. execve()
5. execlp(const char* pathname, ); // 其中的 "l" list;
例如:
ececlp("ls",argv)
execlp("ls","ls","-l",NULL) //最后一个是NULL 前两个参数一样.
char* argv[]={"ls","ls","-l",NULL};
execvp("ls",argv);
6. execvp(const char* pathname,char* argv[]); 其中的 "v" vector 数组.
//pathname: 要执行的程序的名字.(路径) 有 p开头 的会自动在环境变量中找.
//char* argv[]: 把字符串传递给命令行参数
例如:execvp(const char* pathname,char* argv[]);
| 传值 argv[0] 都是可执行文件名.
main(int argc,char* argv[]);
-------------------------------------------------------------------------------
exec 的程序范例: