unix环境编程练习 (1)

来源:互联网 发布:小说阅读软件下载 编辑:程序博客网 时间:2024/05/16 05:45

函数练习

1.对mmap映射地址操作

mmap(), fstat()

mmap(): 将文件和设备空间映射到内存中,内存操作比磁盘更快。映射成功返回内存地址,是被返回-1.之后可以直接对映射的地址进行操作。
fstat()获取文件的状态。

#include <stdio.h>#include <unistd.h>#include <sys/mman.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdlib.h>#include <errno.h>int main(){    int fd=open("doc1",O_RDONLY|O_CREAT,0755);    if(fd == -1){        perror("open ");        exit(1);    }    struct stat info;    fstat(fd,&info);    /* start set NULL, means system set it. */    /* PROT_READ means memory can be read. */    /* MAP_PRIVATE means create a copy file, not influce origin file. */    void *start=mmap(NULL,info.st_size,PROT_READ,MAP_PRIVATE,fd,0);    if(start == MAP_FAILED) {        perror("mmap ");        exit(1);    }    printf("%s",(char *)start);    munmap(start,info.st_size);    close(fd);    return 0;}

本程序将打印文件的内容。如果文件的内容为空,那么将会出现,invalid argument的错误。

2.从标准输入到标准输出

read(), write()

#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>int main(){    int n;    char buf[1000];    while((n=read(STDIN_FILENO,buf,1000))>0){        //printf("output: ");        if(write(STDOUT_FILENO,buf,n)!=n){             printf("write error\n");        }    }    if(n<0) printf("read error\n");    return 0;}/*$ ./stdin_out I sfI sfsdsdsdfsdfsdfsdf//output: output: output: */

read()函数是你输入什么,它读取什么的严格类函数。(除了ctrl+D,ctrl+C等特殊情况)

3.查看标准输入的读写属性

fcntl()

使用fcnt()查看文件的属性。

#include <unistd.h>#include <stdio.h>#include <fcntl.h>int main(){    int flag=fcntl(STDIN_FILENO,F_GETFL,0);    if(flag<0) {        perror("error: ");        return -1;    }    int result=flag & O_ACCMODE;    if(result == O_RDONLY){        printf("stdin read only\n");    }    else if(result == O_WRONLY){        puts("stdin write only");    }    else if(result == O_RDWR){        puts("stdin read and write");    }    else puts("stdin unknown mode");    if(flag & O_APPEND) puts("stdin append");    if(flag & O_NONBLOCK) puts("stdin nonblock");    return 0;}/*./F_GETFL stdin read and write*/

4.终端交互,创建进程

fork(), fgets(), execlp()

使用fork()克隆一个新的进程。fork()有两个返回值,父进程中返回子进程的ID,子进程返回0。
for fgets():
出现换行字符、读到文件尾或是已读了size-1个字符才停止。最后会加上NULL作为字符串结束, 正常的返回值就是buf指针。
execlp():从PATH 环境变量中查找文件并执行
因为终端输入的命令实则是一个小程序,需要进程资源,所以在这里需要fork新的进程

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/wait.h>#include <string.h>int main(){    char buf[100];    pid_t pid;    int status;    printf("%% "); //out put "%"    while(fgets(buf,100,stdin)!=NULL){  // get cmd from stdin         int len=strlen(buf);         if(buf[len-1]=='\n') buf[len-1]=0;         if((pid=fork())<0) puts("fork error");  //create new process          else if(pid==0){             execlp(buf,buf,NULL);  //execute buf cmd in new process             printf("could not execute %s",buf);             exit(1);         }         if(pid=waitpid(pid,&status,0)<0) puts("waitpid error");         printf("%%");    }    return 0;}/*execute:% ls4.12.sh  dex.sh  doc3       for.sh   t.c  t%dateSat Aug 27 15:55:23 CST 2016%whoroot     pts/1        2016-08-27 10:10 (10.21.1.109)root     pts/0        2016-08-27 09:33 (10.21.1.109)%*/

5.与文件的状态相关的写操作

fcntl()

在doc1文件中追加内容 “I love linux”

#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <string.h>int main(){    int fd=open("doc1",O_RDWR);    int flag=fcntl(fd,F_GETFL,0);    flag|=O_APPEND;    flag=fcntl(fd,F_SETFL,&flag);  // 文件的偏移量到了doc1的末尾    if(flag<0){        perror("fcntl error: ");        return -1;    }    char buff[]="I love linux";    if(write(fd,buff,sizeof(buff))<0){        perror("write error: ");    }    close(fd);    return 0;}

6.读取文件的内容到字符串中

system(), fopen(), fgetc()

system()在使用/bin/bash如果失败则会返回127
看到fopen()可以直接使用字符串打开文件,瞬间喜欢上了它。

#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <stdlib.h>int main(){    int cmd=system("pwd > pwd_r");    if(cmd==127 || cmd==-1){        perror("system error: ");        return -1;    }    FILE *file=fopen("pwd_r","r");    if(file==NULL) {        perror("open file error: ");        return -1;    }    char buff[1005],ch;    int top=0;    while((ch=fgetc(file))!=EOF){        buff[top++]=ch;    }    buff[top]=0;    fclose(file);    printf("%s",buff);    return 0;}/*$ ./fopen_write /home/wei/mycode/test*/

7.使用管道,父进程给子进程写一条消息“hello world.”

pipe(), fork(), read, write()

#include <unistd.h>#include <sys/types.h>#include <stdio.h>#include <string.h>int main(){    int fd[2]; // 0: read 1: write    char buff[50]="hello world";    int result=pipe(fd);    if(result==-1){        perror("create pipe error: ");        return -1;    }    pid_t pid=fork();    if(pid==-1){        perror("fork error: ");        return -1;    }    if(pid>0){   // if this is old process         result=write(fd[1],buff,strlen(buff));        printf("id: %d\n",getpid());        return 0;    }    else {   // new process         read(fd[0],buff,sizeof(buff));        printf("id: %d  string: %s\n",getpid(),buff);    }    return 0;}/*$ ./pipeid: 26517id: 26518  string: hello world*/

8.阻塞的管道

fork()

观察下面的程序:

#include <unistd.h>#include <stdio.h>#include <string.h>int main(){    char buff[]="this message is sent by child process.";    int fd[2];    int result=pipe(fd);    if(result<0) {        perror("pipe error: ");        return -1;    }    pid_t pid=fork();    if(pid<0){        perror("create process error: ");        return -1;    }    else if(pid==0){        close(fd[0]);        int len=strlen(buff);        while(len>0){            int rd=write(fd[1],buff,len);            len-=rd;            if(rd<0){                perror("write error: ");                return -1;            }            else {                printf("has wrote data: %d left data: %d\n",rd,len);            }            sleep(3);            if(len==0) {                    printf("write finished.\n");                  }        }    }    else {        close(fd[1]);        char readbuff[105];        while(1){            int get=read(fd[0],readbuff,105);            if(get<0){                perror("read : ");                return -1;            }            else if(get==0) {                printf("here is no contents.\n");                break;            }            else {                printf("data : %s\n",readbuff);            }        }    }    return 0;}/*$ ./wait_pipe has wrote data: 38 left data: 0    #子进程写入数据data : this message is sent by child process.  #父进程读入数据write finished.    #回到了子进程here is no contents.   #这是父进程//如果我们没有sleep(3)has wrote data: 38 left data: 0   #子进程write finished.   #子进程data : this message is sent by child process. #父进程here is no contents.    #父进程*/

9.消息队列send and recv message.

ftok(), msgget(), fgets()

key_t ftok( const char * fname, int id )
fname是指定的文件名(已经存在的文件名),一般使用当前目录,如:
key_t key = ftok(“.”, 1); id是子序号。只使用8bits(1-255)。
用于保证两个不同用户下的两组相同程序获得互不干扰的IPC键值。
msgget()用于chungking或者打开消息队列。

//send.c:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/msg.h>#include <sys/types.h>#include <sys/ipc.h>#define Max 105typedef struct msgmbuf{    int msg_type;    char msg_text[Max];}MsgBuf;int main(){    printf("send process start: %d\n",getpid());    printf("enter your message to send, and \"end\" will kill both process.\n");    char buff[Max];    MsgBuf sendmsg;    char *msgpath="./me";   // the path of create message    key_t key=ftok(msgpath,'a');    if(key==-1) {        perror("create key error: ");        return -1;    }    int msgid=msgget(key,IPC_CREAT|0777);    if(msgid==-1){        perror("msgget error: ");        return -1;    }    while(1){        printf("please enter msg: ");        fgets(buff,Max,stdin); //file enter contents        sendmsg.msg_type=1;        strcpy(sendmsg.msg_text,buff);        if(msgsnd(msgid,(void *)&sendmsg,Max,0)){            perror("msgsnd error: ");            return -1;        }        if(strcmp(buff,"end\n")==0){            printf("send process end.\n");            return 0;        }    }    return 0;}//recv.c:#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <string.h>#include <sys/ipc.h>#include <sys/types.h>#include <sys/msg.h>#define Max 105typedef struct msgmbuf{    int msg_type;    char msg_text[Max];}MsgBuf;int main(){    printf("recv process start: %d\n",getpid());    char buff[Max];    char *msgpath="./me";    key_t key=ftok(msgpath,'a');    int msgid=msgget(key,IPC_CREAT|0777);    if(msgid==-1){        perror("msgget error: ");        return -1;    }    MsgBuf recmsg;    while(1){        if(msgrcv(msgid,(void *)&recmsg,Max,0,0)==-1){            perror("msgrcv error: ");            return -1;        }        if(strcmp(recmsg.msg_text,"end\n")==0){            printf("recv process end.\n");            break;        }        printf("recv msg: %s",recmsg.msg_text);    }    return 0;}/*$ ./sendsend process start: 20436enter your message to send, and "end" will kill both process.please enter msg: heheplease enter msg: I love youplease enter msg: endsend process end../recvrecv process start: 20437recv msg: heherecv msg: I love yourecv process end.*/

10.不同进程利用共享内存通信

shmget(), shmctl()

// myshm.h #include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/shm.h>#include <sys/ipc.h>#include <string.h>#define Size 105// shm.c#include "myshm.h"int main(){    key_t key=ftok("./doc",'a');    int shmid=shmget(key,Size,IPC_CREAT|IPC_EXCL|0777);    if(shmid==-1){        puts("shmared memory exit. here is client.");        if((shmid=shmget(key,Size,0))==-1){ //the third number is 0 means we can get the exit memory id.            perror("shmget error: ");            return -1;        }    }    else puts("created new shared memory");    char buff[105], *content=NULL;    printf("If you enter \"read\", we can get contents, or \"enter\", you can input new things into shared memory.\Other words will kill process. \n");    while(1){        printf("%% ");        if(fgets(buff,Size,stdin)<0){            perror("fgets error: ");            return -1;        }        content=(char *)shmat(shmid,0,0);        if(content == (char *)-1){            perror("shmat: ");            return -1;        }        if(strncmp(buff,"read",4)==0){            printf("data: \n%s",content);        }        else if(strncmp(buff,"enter",5)==0){            fgets(buff,Size,stdin);            strcat(content,buff);            printf("wrote it.");        }        else {            /*IPC_RMID 命令实际上不从内核删除一个段,而是仅仅把这个段标记为删除,\             * 实际的删除发生在最后一个进程离开这个共享段时。*/            shmctl(shmid,IPC_RMID,0);            printf("the process end, By.\n");            break;        }    }    return 0;}/*./shmcreated new shared memoryIf you enter "read", we can get contents, or "enter", you can input new things into shared memory.Other words will kill process. % enterI love youwrote it.% readdata: I love you% enter hello world wrote it.% sthe process end, By../shmshmared memory exit. here is client.If you enter "read", we can get contents, or "enter", you can input new things into shared memory.Other words will kill process. % readdata: I love you% readdata: I love youhello world% sthe process end, By.*/

11.自定义中断信号SIGINT的处理函数

signal()

#include <stdio.h>#include <stdlib.h>#include <signal.h>void stop(int sig){    printf("ctrl + c stops it!\n");    exit(0);}int main(){    signal(SIGINT,stop);    while(1){        puts("hello world");    }    return 0;}/*./signalhello worldhello worldhello worldhello worldhello worldhello world^Chello worldctrl + c stops it!*/

12.线程创建与等待

pthread_create(), pthread_join(), pthread_self()

#include <stdio.h>#include <pthread.h>#include <unistd.h>void *thread_show(void *args){    int *thread_arg=(int *)args;    printf("I'm thread %lu, counter is %d\n",pthread_self(),*thread_arg); // g(long int)syscall(178),gettid() means syscall(178)     sleep(1);}int main(){    int i,ret;    pthread_t thread[6];    for(i=0;i<6;i++){        printf("here is thread: %d\n",i);        ret=pthread_create(&thread[i],NULL,thread_show,&i);         // 第三个参数是线程的运行函数,第四个参数是运行函数的参数        if(ret!=0) printf("error: %d thread can't be created.\n",i);    }    for(i=0;i<6;i++){  //等待着线程结束,此时的i等于0        pthread_join(thread[i],NULL);    }    return 0;}/*./pthread here is thread: 0here is thread: 1here is thread: 2I'm thread 140437552871168, counter is 2I'm thread 140437544478464, counter is 2here is thread: 3here is thread: 4here is thread: 5I'm thread 140437527693056, counter is 4I'm thread 140437519300352, counter is 5I'm thread 140437536085760, counter is 3I'm thread 140437510907648, counter is 0*/
0 0