linux应用程序设计(一)——文件、时间编程及进程控制

来源:互联网 发布:报纸编辑软件 编辑:程序博客网 时间:2024/05/22 11:48

本文中的代码是国嵌实验手册上的,并非原创,自己添上注释。

第一部分:文件编程

linux中文件编程可以使用两种方式:linux系统调用和C语言库函数。前者依赖于linux系统,后者和操作系统是独立的,在任何操作系统下,使用C语言库函数操作文件的方法都是相同的。


实验2-1-1 文件编程—文件创建

一、源代码及注释

/*需求:创建一个可读可写的文件*/

#include <stdio.h>      /*输入输出头文件*/
#include <stdlib.h>     /*实用函数头文件*/
#include <sys/types.h>  /*类型头文件*/
#include <sys/stat.h>   /*文件状态头文件*/
#include <fcntl.h>      /*文件控制头文件*/


void create_file(char *filename)
{
    /*判断创建的文件是否成功*/
    if(creat(filename,0666)<0)/*若创建成功内核向进程返回文件描述符(非负数)*/
    {
        printf("create file %s failure!\n",filename);
        exit(EXIT_FAILURE);
    }
    else
        printf("create file %s success!\n",filename);
}


/*函数功能:主函数*/
int main(int argc,char *argv[]) /*argc是命令行参数的数目,argv是指向参数的各指针所构成的数组(指针数组)*/
{
    /*判断用户是否输入文件名*/
    if(argc<2) /*命令行参数只有本程序文件名*/
    {
        printf("you haven't input filename,please try again!\n");
        exit(EXIT_FAILURE);/*正常结束进程函数,终止状态为EXIT_FAILURE=1,在终端echo $?打印终止码*/
    }
    create_file(argv[1]);
    exit(EXIT_SUCCESS);
}

二、详点说明

        1、文件创建函数creat的参数说明——“0666”,不难理解6代表的是可读可写,在运行该程序后,创建出的文件的权限是这样的“-rw-r--r--",即真正可读可写的只有该用户自己。

        2、exit()和return()函数的区别:

         exit() 结束当前进程/当前程序/,在整个程序中,只要调用 exit ,就结束。
   return() 是当前函数返回,当然如果是在主函数main, 自然也就结束当前进程了,如果不是,那就是退回上一层调用。


实验2-2-2          文件编程——文件拷贝

一、源代码

/*使用库函数实现文件copy功能*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 1024


int main(int argc,char *argv[])
{
    FILE *from_fd;   //定义FILE结构体,存放打开源文件返回值
    FILE *to_fd;
    long file_len=0;
    char buffer[BUFFER_SIZE];


    /*判断入参是否为三,即本文件名,源文件名和目的文件名*/
    if(argc!=3)
    {
        printf("Usage:%s fromfile tofile\n",argv[0]);
        exit(EXIT_FALURE);
    }


    /*打开源文件*/
    if((from_fd=fopen(argv[1],"rb"))==NULL)
    {
        printf("Open %s Error!\n",argv[1]);
        exit(EXIT_FALURE);
    }


    /*创建目的文件*/
    if((to_fd=fopen(argv[2],"wb"))==NULL)
    {
        printf("Open %s Error!\n",argv[2]);
        exit(EXIT_FALURE);
    }


    /*测试源文件大小*/
    fseek(from_fd,0L,SEEK_END);   //将源文件指针指到文件尾
    file_len=ftell(from_fd);      //取得文件指针位置,返回位置值,即文件大小
    fseek(from_fd,0L,SEEK_SET);   //将源文件指针指回到文件头
    printf("from file size is %d\n",file_len);


    /*进行文件拷贝*/
    while(!feof(from_fd))    //检查文件指针是否到了文件尾
    {
        fread(buffer,BUFFER_SIZE,1,from_fd);  //从源文件读取BUFFER_SIZE*1,存入buffer中
        /*判断能否一次写完*/
        if(BUFFER_SIZE>=file_len)
        {
            fwrite(buffer,BUFFER_SIZE,1,to_fd);
        }
        else
        { 
            fwrite(buffer,file_len,1,to_fd);
            file_len=file_len-BUFFER_SIZE;    
        }
        memset(buffer,0,BUFFER_SIZE);  //将buffer中长度BUFFER_SIZE的数据写零
    }
    fclose(from_fd);
    fclose(to_fd);
    exit(EXIT_SUCCESS);
}

二、详点说明

1、关于FILE结构体:FILE定义的数据类型是一种结构体类型,FILE结构体与具体的编译器和系统有关。Linux系统下,在/usr/include/stdio.h中定义为typedef struct_IO_FILE  FILE,即一种结构体类型。

2、源程序中本来使用bzero()函数将buffer清零,故了解下这两个函数的用法和区别:

bzero原型:void bzero(void *s,int n);

        用法:#include <strings.h>

        功能:置字符串s的前n个字节为零且包括'\0'。

        说明:bzero无返回值,并且使用strings.h头文件,strings.h曾经是POSIX标准的一部分,但是在POSIX.1-2001标准里面,这些函数被标记为了遗留函数而不推荐使用。在POSIX.1-2008标准里已经没有这些函数了。推荐使用memset替代bzero。


第二部分:时间编程

首先了解下三种时间类型:格林威治时间、日历时间(从某一标准时间点到此时经过的秒数)、本地时间。

实验2-1-3 时间编程——获取本地时间

一、源代码

/*获取本地时间,以字符串形式显示*/


#include <stdio.h>
#include <time.h>


int main()
{  
    time_t lt;        //定义time_t结构(实际就是long类型)变量lt,存放日历时间,即秒数
    struct tm *ptr;   //定义TM结构类型变量,以TM结构存放时间信息
    
    /*获取日历时间*/
    lt=time(NULL);


    /*转换为本地时间*/
    ptr=localtime(&lt);


    /*以本地时间的字符串方式打印*/
    printf("%s\n",asctime(ptr));
    
    /*以本地时间的字符串方式打印*/
    printf("%s\n",ctime(&lt));
 
    return 0;
}


 

第三部分:进程控制

进程有三种状态:就绪态、执行态、阻塞态。

实验2-2-1 fork创建子进程

一、源代码

/*需求:编写程序创建一子进程,分别在父进程和子进程中打印进程ID*/


#include <unistd.h>    /*linux标准头文件*/
#include <sys/types.h> /*类型头文件*/
#include <stdio.h>
#include <stdlib.h> 
#include <string.h>
#include <errno.h>     /*错误号头文件*/


int main(void)
{
    pid_t child;       


    /*创建子进程*/
    if((child=fork())<0)
    {
        printf("Fork Error:%s\n",strerror(errno)); /*通过参数errno将错误号,转换为输出错误信息*/
        exit(1);
    }
    else
        if(child==0)  //子进程
        {
            printf("I am the child:%d\n",getpid());
            exit(0);
        }


        else  //父进程
        {
            printf("I am the father:%d\n",getpid());
            return 0;
        }
}


实验2-2-2 vfork创建子进程


一、源代码

/*需求:编写程序使用vfork创建一子进程,分别在父进程和子进程中打印进程ID,并观察父子进程的运行顺序*/


#include <unistd.h>     /*linux标准头文件*/
#include <sys/types.h>  /*类型头文件*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>      /*错误号头文件*/


int main(void)
{
    pid_t child;


    /*创建子进程*/
    if((child=vfork())<0)
    {
        printf("Fork Error:%s\n",strerror(errno));
        exit(1);
    }
    else
        if(child==0)  //子进程
        {
            sleep(1);  //子进程睡眠一秒
            printf("I am the child:%d\n",getpid());
            exit(0);
        }


        else  //父进程
        {
            printf("I am the father:%d\n",getpid());
            return 0;
        }
}


二、详点说明

fork与vfork的区别:

1、fork:子进程拷贝父进程的数据段,即子进程创建后与父进程相互独立运行

      vfork:子进程共享父进程的数据段。

2、fork:父、子进程的运行顺序不确定

              vfork:父进程必须等待子进程运行结束才能运行。


实验2-2-3 exec函数族

一、源代码

/*需求:使用系统调用execl函数创建一个文件*/


#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>


int main(int agrc,char *argv[])
{
    /*判断入参有没有传入文件名*/
    if(agrc<2)
    {
        perror("You haven't input the filename,please try again!\n");
        exit(1);
    }


    /*调用execl函数,用可执行程序file_creat替换本进程*/
    if(execl("./file_creat","file_creat",argv[1],NULL)<0)
        perror("execl error!\n");    /*perror将你输入的信息和errno对应的错误信息一起打印出来*/
}


二、详点说明

perror函数、strerror函数、erron的关系和区别:

1、errno是错误码,在errno.h头文件中;

2、strerror函数,通过参数errno将错误码对应的错误信息返回;

3、perror函数,将你输入的信息和errno对应的错误信息一起返回。


实验2-2-4 进程等待

一、源代码

/*需求:编写程序创建一子进程,父进程需要等待子进程运行完后才能执行*/


#include <unistd.h>     /*linux标准头文件*/
#include <sys/types.h>  /*类型头文件*/
#include <sys/wait.h>   /*等待调用头文件*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>      /*错误号头文件*/


int main(void)
{
    pid_t child;


    /*创建子进程*/
    if((child=fork())<0)
    {
        printf("Fork Error:%s\n",strerror(errno));
        exit(1);
    }
    else
        if(child==0)  //子进程
        {
            printf("the child process is run\n");
            sleep(1);  //子进程睡眠一秒钟,但并没有去执行父进程
            printf("I am the child:%d\n",getpid());
            exit(0);
        }


        else  //父进程
        {
            wait(NULL); //阻塞父进程,直到子进程退出
            printf("the father process is run\n");
            printf("I am the father:%d\n",getpid());
            return 0;
        }
}


二、详点说明

wait()参数设置为NULL,将不返回子进程结束状态值。


最后,附上个人觉得比较有用的上网资料

 Linux 常用C函数                  点击打开链接

 Linux头文件汇总                 点击打开链接


原创粉丝点击