zoukankan      html  css  js  c++  java
  • 第十一周学习总结

    1.argv(文件夹)-argtest.c文件

    #include <stdio.h>
    #include <stdlib.h>
    #include "argv.h"//该函数库中包括freemakeargv.c及makeargv.c函数的调用

    int main(int argc, char *argv[]) 
    {
    char delim[] = " \t";//制表符
    int i;
    char **myargv;//见下方解释
    int numtokens;

    if (argc != 2)//如果输入的命令字符个数不等于2,就输出标准错误 
    {
    fprintf(stderr, "Usage: %s string\n", argv[0]);
    return 1;

    if ((numtokens = makeargv(argv[1], delim, &myargv)) == -1) 
    {
    fprintf(stderr, "Failed to construct an argument array for %s\n", argv[1]);//翻译过来就是无法构造一个参数数组
    return 1;

    printf("The argument array contains:\n");
    for (i = 0; i < numtokens; i++)
    printf("%d:%s\n", i, myargv[i]);
    execvp(myargv[0], myargv);

    return 0;
    }
    另附加 freemakeargv.c及makeargv.c函数

    #include <stdlib.h>
    #include "argv.h"

    void freemakeargv(char **argv) {
    if (argv == NULL)
    return;
    if (*argv != NULL)
    free(*argv);
    free(argv);
    }
    /*-----------------------------------------------------------------------------*/
    #include <errno.h>
    #include <stdlib.h>
    #include <string.h>
    #include "argv.h"

    int makeargv(const char *s, const char *delimiters, char ***argvp)//见下方解释
    {
    int error;
    int i;
    int numtokens;
    const char *snew;
    char *t;

    if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) 
    {
    errno = EINVAL;
    return -1;
    }
    *argvp = NULL;//把字符串数组置为空 
    snew = s + strspn(s, delimiters);//返回字符串s开头连续包含字符串delimiters内的字符数目 
    if ((t = malloc(strlen(snew) + 1)) == NULL) 
    return -1; 
    strcpy(t, snew); 
    numtokens = 0;
    if (strtok(t, delimiters) != NULL)//关于strtok函数的用法见下方
    for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ;

    if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL)
    {//malloc函数请求分配了numtokens+1个字节的空间;如果是返回值是NULL说明分配不成功
    error = errno;
    free(t);//释放malloc函数给指针变量分配的内存空间的函数。使用后该指针变量一定要重新指向NULL。
    errno = error;
    return -1; 

    if (numtokens == 0) 
    free(t);
    else 
    {
    strcpy(t, snew);
    **argvp = strtok(t, delimiters);
    for (i = 1; i < numtokens; i++)
    *((*argvp) + i) = strtok(NULL, delimiters);

    *((*argvp) + numtokens) = NULL; 
    return numtokens;

    关于该系列代码的难点理解 

    1.为什么是* *myargv?

     **相相当于二级指针,char **就是指向字符型指针的指针。最常使用的地方就是 int main(int argc,char **argv),相当于int main(int argc,char *argv[])。也就是说,可以看作是指向了字符串数组

    2.为什么是 int makeargv(const char *s, const char *delimiters, char * **argvp)

    把最后一个参数理解为向字符串数组取地址

    3.errno与error区别?

    前者是记录系统最后一次错误的函数;后者是系统错误

    2.env文件夹-environ.c文件

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

    int main(void)
    {
    printf("PATH=%s\n", getenv("PATH"));//getenv函数用来取得参数PATH环境变量的值,执行成功则返回该内容的指针
    setenv("PATH", "hello", 1);//见下方解释
    printf("PATH=%s\n", getenv("PATH"));
    #if 0
    printf("PATH=%s\n", getenv("PATH"));
    setenv("PATH", "hellohello", 0);
    printf("PATH=%s\n", getenv("PATH"));


    printf("MY_VER=%s\n", getenv("MY_VER"));//版本
    setenv("MY_VER", "1.1", 0);
    printf("MY_VER=%s\n", getenv("MY_VER"));
    #endif
    return 0;
    }
    【setenv函数的作用?】 

    setenv用来在本次函数运行的过程中增加或者修改环境变量。当最后一个参数不为0的时候,原来的内容会被修改为第二个参数所指的内容。

    3.env文件夹-environvar.c文件

    #include <stdio.h>
    int main(void)
    {
    extern char **environ;
    int i;
    for(i = 0; environ[i] != NULL; i++)
    printf("%s\n", environ[i]);

    return 0;
    }
    environ变量是什么?

    该变量指向一个叫“environment”的字符串数组。包括USER(登录用户的名字),LOGNAME(与user类似),HOME(用户登录目录),LANG(地域名),PATH等

    什么是execlp函数?

    从PATH环境变量中查找文件并执行。原型:int execlp(const char *file,const char *arg,……); 从PATH环境变量所指的目录中查找符号参数file的文件名,然后将第二个及以后的参数当作该文件的argv[0],argv[1],……,最后一个参数必须用NULL结束。

    4.pipe文件夹-consumer.c文件

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <fcntl.h>
    #include <limits.h>
    #include <sys/types.h>
    #include <sys/stat.h>

    #define FIFO_NAME "/tmp/myfifo"
    #define BUFFER_SIZE PIPE_BUF
    int main()
    {
    int pipe_fd;
    int res;

    int open_mode = O_RDONLY;
    char buffer[BUFFER_SIZE + 1];
    int bytes = 0;

    memset(buffer, 0, sizeof(buffer));

    printf("Process %d opeining FIFO O_RDONLY \n", getpid());
    pipe_fd = open(FIFO_NAME, open_mode);
    printf("Process %d result %d\n", getpid(), pipe_fd);

    if (pipe_fd != -1) {
    do {
    res = read(pipe_fd, buffer, BUFFER_SIZE);
    bytes += res;
    } while (res > 0);
    close(pipe_fd);
    } else {
    exit(EXIT_FAILURE);
    }

    printf("Process %d finished, %d bytes read\n", getpid(), bytes);
    exit(EXIT_SUCCESS);
    }
    1.PIPE_BUF的值是多少?

    4096字节

    2.memset函数用法?

    原型:memset(void *s,int ch,size_t n);将s中前n个字节用ch替换并返回s

    3.open函数用法?

    open(const char *pathname,int flags);第一个参数是欲打开的文件路径字符串,第二个参数是打开方式

    4.FIFONAME是什么?

    这里需要补充一下fifo的含义,它是一种文件类型,可以通过查看文件stat结构中的stmode成员的值来判断文件是否是FIFO文件。fifo是用来在进程中使用文件来传输数据的,也具有管道特性,可以在数据读出的时候清除数据。

    5.env文件夹-producer文件

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <fcntl.h>
    #include <limits.h>
    #include <sys/types.h>
    #include <sys/stat.h>

    #define FIFO_NAME "/tmp/myfifo"
    #define BUFFER_SIZE PIPE_BUF
    #define TEN_MEG (1024 * 1024 * 10)

    int main()
    {
    int pipe_fd;
    int res;
    int open_mode = O_WRONLY;

    int bytes = 0;
    char buffer[BUFFER_SIZE + 1];

    if (access(FIFO_NAME, F_OK) == -1) {//检查文件是否有相应的权限
    res = mkfifo(FIFO_NAME, 0777);//依据FIFO_NAME创建fifo文件,0777依次是相应权限
    if (res != 0) {
    fprintf(stderr, "Could not create fifo %s \n",
    FIFO_NAME);
    exit(EXIT_FAILURE);
    }
    }

    printf("Process %d opening FIFO O_WRONLY\n", getpid());
    pipe_fd = open(FIFO_NAME, open_mode);
    printf("Process %d result %d\n", getpid(), pipe_fd);

    if (pipe_fd != -1) {
    while (bytes < TEN_MEG) {
    res = write(pipe_fd, buffer, BUFFER_SIZE);
    if (res == -1) {
    fprintf(stderr, "Write error on pipe\n");
    exit(EXIT_FAILURE);
    }
    bytes += res;
    }
    close(pipe_fd);
    } else {
    exit(EXIT_FAILURE);
    }

    printf("Process %d finish\n", getpid());
    exit(EXIT_SUCCESS);
    }

    6.env文件夹-testmf.c文件

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>

    int main()//就是创建fifo文件
    {
    int res = mkfifo("/tmp/myfifo", 0777);
    if (res == 0) {
    printf("FIFO created \n");
    }
    exit(EXIT_SUCCESS);
    }

    (修改testmf.c代码)

    (修改之后的执行结果)
    7.pipe文件夹-pipe.c文件

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

    #define oops(m,x) //当linux系统执行代码遇到问题时,就会报告oops
    { perror(m); exit(x); }

    int main(int ac, char **av)
    {
    int thepipe[2], newfd,pid;

    if ( ac != 3 ){//输入的命令长度不等于3
    fprintf(stderr, "usage: pipe cmd1 cmd2\n");
    exit(1);
    }
    if ( pipe( thepipe ) == -1 ) //以下是各种错误 
    oops("Cannot get a pipe", 1);

    if ( (pid = fork()) == -1 ) 
    oops("Cannot fork", 2);

    if ( pid > 0 ){ 
    close(thepipe[1]);

    if ( dup2(thepipe[0], 0) == -1 )
    oops("could not redirect stdin",3);

    close(thepipe[0]); 
    execlp( av[2], av[2], NULL);
    oops(av[2], 4);
    }

    close(thepipe[0]);

    if ( dup2(thepipe[1], 1) == -1 )
    oops("could not redirect stdout", 4);

    close(thepipe[1]); 
    execlp( av[1], av[1], NULL);
    oops(av[1], 5);
    }

    8.pipe文件夹-stdinredir1.c文件

    #include <stdio.h>
    #include <fcntl.h>

    int main()
    {
    int fd ;
    char line[100];

    fgets( line, 100, stdin ); printf("%s", line );//就是打印输入的字符串
    fgets( line, 100, stdin ); printf("%s", line );
    fgets( line, 100, stdin ); printf("%s", line );

    close(0);
    fd = open("/etc/passwd", O_RDONLY);
    if ( fd != 0 ){//打开或者创建失败的时候才会执行
    fprintf(stderr,"Could not open data as fd 0\n");
    exit(1);
    }

    fgets( line, 100, stdin ); printf("%s", line );
    fgets( line, 100, stdin ); printf("%s", line );
    fgets( line, 100, stdin ); printf("%s", line );
    }

    9.pipe文件夹-testtty.c文件

    #include <unistd.h>
    int main()
    {
    char *buf = "abcde\n";
    write(0, buf, 6);
    }
    write函数 

    write(int handle,void *buf,int nbyte); 第一个参数是文件描述符,第二个参数是指向一端内存单元的指针,第三个参数是要写入指定文件的字节个数;成功时返回字节个数,否则返回-1。

    10.signal文件夹-sigactdemo1.c文件

    #include <stdio.h>
    #include<unistd.h>
    #include <signal.h>
    #define INPUTLEN 100
    void inthandler(); 
    int main()
    {
    struct sigaction newhandler;//见下方解释 
    sigset_t blocked; //信号集,用来描述信号的集合,与信号阻塞相关函数配合使用
    char x[INPUTLEN];
    newhandler.sa_handler = inthandler; //函数指针
    newhandler.sa_flags = SA_RESTART|SA_NODEFER
    |SA_RESETHAND; //sa_flags是一个位掩码。这里,第一个参数使得被信号打断的一些原语“正常返回”
    sigemptyset(&blocked); 
    sigaddset(&blocked, SIGQUIT); 
    newhandler.sa_mask = blocked; 
    if (sigaction(SIGINT, &newhandler, NULL) == -1)
    perror("sigaction");
    else
    while (1) {
    fgets(x, INPUTLEN, stdin);
    printf("input: %s", x);
    }
    return 0;
    }
    void inthandler(int s)
    {
    printf("Called with signal %d\n", s);
    sleep(s * 4);
    printf("done handling signal %d\n", s);
    }
    具体参见http://www.cnblogs.com/gogly/articles/2416989.html 

    sigaction结构体,用来查询或设置信号处理方式。比如它指定了对特定信号的处理,信号所传递的信息,信号处理函数执行过程中应该屏蔽掉哪些函数等。

    11.signal文件夹-sigdemo1.c文件夹

    #include <stdio.h>
    #include <signal.h>
    void f(int); 
    int main()
    {
    int i;
    signal( SIGINT, f ); 
    for(i=0; i<5; i++ ){ 
    printf("hello\n");
    sleep(2);
    }

    return 0;
    }

    void f(int signum) 
    {
    printf("OUCH!\n");
    }
    这样的代码是无法在输出的时候体现出对f的调用的。我认为其中signal( SIGINT, f );这一句中,因为f的返回值是“void”,所以无法体现。

    补充:signal函数,原型 signal(参数1,参数2);,其中参数1是我们进行处理的信号,参数2是我们处理的方式。

    什么是execv函数? 

    原型:int execv(const char *pathname,char *const argv[]);装入并运行其他程序 对比:execvp函数原型: int execvp(const char *file,char *const argv[]);

    12.signal文件夹-sigdemo3.c文件

    #include <stdio.h>
    #include<string.h>
    #include <signal.h>
    #include<unistd.h>

    #define INPUTLEN 100

    int main(int argc, char *argv[])
    {
    void inthandler(int);
    void quithandler(int);
    char input[INPUTLEN];
    int nchars;

    signal(SIGINT, inthandler);//^C 
    signal(SIGQUIT, quithandler);//^\

    do {//输入什么,就输出什么(在read函数不发生错误的情况下)
    printf("\nType a message\n");
    nchars = read(0, input, (INPUTLEN - 1));
    if (nchars == -1)
    perror("read returned an error");
    else {
    input[nchars] = '\0';
    printf("You typed: %s", input);
    }
    }
    while (strncmp(input, "quit", 4) != 0);//只有输入quit的时候才会退出
    return 0;
    }

    void inthandler(int s)
    {
    printf(" Received signal %d .. waiting\n", s);
    sleep(2);
    printf(" Leaving inthandler \n");
    }

    void quithandler(int s)
    {
    printf(" Received signal %d .. waiting\n", s);
    sleep(3);
    printf(" Leaving quithandler \n");
    }

    13.exec3.c文件

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

    int main()
    {
    char *arglist[3];
    char*myenv[3];
    myenv[0] = "PATH=:/bin:";
    myenv[1] = NULL;

    arglist[0] = "ls";
    arglist[1] = "-l";
    arglist[2] = 0 ;
    printf("* * * About to exec ls -l\n");
    // execv( "/bin/ls" , arglist );
    // execvp( "ls" , arglist );
    // execvpe("ls" , arglist, myenv);

    execlp("ls", "ls", "-l", NULL);
    printf("* * * ls is done. bye\n");
    }

  • 相关阅读:
    Python subprocess方法
    Python hashlib、hmac加密模块
    mysql binlog详解
    Nginx 关键字详解
    账号笔记
    Python configparser模块
    Python yaml处理
    Linux && 与 ||
    spring boot 学习(十一)使用@Async实现异步调用
    spring boot 学习(十)SpringBoot配置发送Email
  • 原文地址:https://www.cnblogs.com/baka/p/5008221.html
Copyright © 2011-2022 走看看