分类: LINUX
2009-10-09 21:44:36
在linux下编写第一个程序时,会看到如下的函数:
#inlcudexxx
...
int main(int argc,char *argv[])
{
...
exit(0);
}
或
#inlcudexxx
...
int main()
{
...
exit(0);
}
初次接触linux编程的人会问:怎么主函数的入口多了两个变量?怎么不用这两个变量也可以?
其实: int main(int argc,char *argv[]) 是 UNIX 和 Linux 中的标准写法,而 int main() 只是 UNIX 及 Linux 默许的用法。那就是随便你怎么用了,看你自己的需要了,呵呵。argc 是外部命令参数的个数,argv[] 存放各参数的内容。举个例子应该会更加深理解:
先用vi创建一个文件text.c
然后按a输入文本。
#include
int main(int argc,char *argv[])
{
int i = 0;
for(;i
{
printf("%s\n",argv[i]);
}
return 0;
}
输入完成后,按ESC然后按“shift+:”,输入wq并回车保存文件。
把上面的程序编译一下.
gcc -o text text.c
int main(int argc,char *argv[])
记住,第1个参数是命令行参数的个数,char *argv[]是一个存放字符指针的数组, 每个指针指向一个具体的命令行参数(字符串)。运行一下,不难发现:
[root@ReinSquid code]# ./text haha 1
./text
haha
1
ANSI C定义的主函数的参数实际上是可变长的,最多可以为三个.第三个参数与第二个参数类似,存放环境变量。
再看一个程序,在某一目录下新建file.c 和1.c文件,其内容如下:
/*file.c*/
#include
#include
#include
#include
#include
#include
#include
#define BUFFER_SIZE 1024
int main(int argc,char **argv)
{
int from_fd,to_fd;
int bytes_read,bytes_write;
char buffer[BUFFER_SIZE];
char *ptr;
if(argc!=3)
{
fprintf(stderr,"Usage:%s fromfile tofile\n\a",argv[0]);
exit(1);
}
/* 打开源文件 */
if((from_fd=open(argv[1],O_RDONLY))==-1)
{
fprintf(stderr,"Open %s Error:%s\n",argv[1],strerror(errno));
exit(1);
}
/* 创建目的文件 */
if((to_fd=open(argv[2],O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))==-1)
{
fprintf(stderr,"Open %s Error:%s\n",argv[2],strerror(errno));
exit(1);
}
/* 以下代码是一个经典的拷贝文件的代码 */
while(bytes_read=read(from_fd,buffer,BUFFER_SIZE))
{
/* 一个致命的错误发生了 */
if((bytes_read==-1)&&(errno!=EINTR)) break;
else if(bytes_read>;0)
{
ptr=buffer;
while(bytes_write=write(to_fd,ptr,bytes_read))
{
/* 一个致命错误发生了 */
if((bytes_write==-1)&&(errno!=EINTR))break;
/* 写完了所有读的字节 */
else if(bytes_write==bytes_read) break;
/* 只写了一部分,继续写 */
else if(bytes_write>;0)
{
ptr+=bytes_write;
bytes_read-=bytes_write;
}
}
/* 写的时候发生的致命错误 */
if(bytes_write==-1)break;
}
}
close(from_fd);
close(to_fd);
exit(0);
}
/*1.c*/
#include
int main(void)
{
printf(“copy me!\n”);
exit(0);
}
使用命令GCC –o file file.c后,输入./file 1.c 2.c,可以发现1.c的内容变为1.c的内容了。
现在该知道main函数入口参数中两个变量的用法了吧!
再看一下exit的用法,
exit(0) 表示正常退出, exit(1)、exit(-1)表示程序异常退出;
exit() 结束当前进程/当前程序,在整个程序中,只要调用exit,就结束;
return() 是当前函数返回,当然如果是在主函数main, 自然也就结束当前进程了,如果不是,那就是退回上一层调用。在多个进程时.如果有时要检测上进程是否正常退出的.就要用到上个进程的返回值。当exit(1)表示进程正常退出,返回1;当exit(0)表示进程非正常退出,返回0。exit()函数定义在 stdlib.h中,而_exit()定义在unistd.h中,exit和_exit函数用于正常终止一个程序:_exit立即进入内核,exit则先执行一些清除处理, (包括调用执行各终止处理程序,关闭所有标准I/O流等),然后进入内核。exit()函数与_exit()函数最大的区别就在于exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,就是图中的“清理I/O缓冲”一项。在Linux 的标准函数库中,有一套称作“高级I/O”的函数,我们熟知的printf()、fopen()、fread()、fwrite()都在此列,它们也被称作“缓冲I/O(buffered I/O)”,其特征是对应每一个打开的文件,在内存中都有一片缓冲区,每次读文件时,会多读出若干条记录,这样下次读文件时就可以直接从内存的缓冲区中读取,每次写文件的时候,也仅仅是写入内存中的缓冲区,等满足了一定的条件(达到一定数量,或遇到特定字符,如换行符\n和文件结束符EOF),再将缓冲区中的内容一次性写入文件,这样就大大增加了文件读写的速度,但也为我们编程带来了一点点麻烦。如果有一些数据,我们认为已经写入了文件,实际上因为没有满足特定的条件,它们还只是保存在缓冲区内,这时我们用_exit()函数直接将进程关闭,缓冲区中的数据就会丢失,反之,如果想保证数据的完整性,就一定要使用exit()函数。
请看以下例程:
/* exit2.c */
#include
#include
main()
{
printf("output begin\n");
printf("content in buffer");
exit(0);
}
编译并运行:
gcc -o exit2 exit2.c
./exit2
output begin
content in buffer
/* _exit1.c */
#include
#include
main()
{
printf("output begin\n");
printf("content in buffer");
_exit(0);
}
编译并运行:
gcc _exit1.c -o _exit1
./_exit1
output begin
另外,也有形如如下的程序返回:
int main(int argc,char *argv[])
{
...
return(0);
}
return() 是当前函数返回,当然如果是在主函数main, 自然也就结束当前进程了,如果不是,那就是退回上一层调用。
对linux初学者来说,掌握linux下第一个程序设计,并理解基本程序结构非常重要。