linux命令///

预编译:将宏注释等进行替换,头文件展开(函数声明) gcc - E main.c -o main.i,编译:检查语法语义错误,生成汇编代码 gcc -S main.i -o main.s  汇编:将汇编代码转变为机器语言(二进制代码) gcc -c main.s -i main.o,链接:将调用的函数和我们的应用程序进行链接  gcc main.o -o main

sudo su :管理员登陆 exit:退出登录   改密码:passwd 用户名  添加新用户:adduser 用户名         boot->内核  etc->配置文件 lib->库文件 uer->安装的软件 dev->配置文件  bin->命令

vim:分为命令模式,编辑模式,末行模式

删除用户:deluser 用户名  (一般在/etc/passwd下查看用户信息)

root:管理员id号为0;stu:用户,id号从1000开始

cd:切换路径  ls:显示当前位置文件 pwd:显示当前位置  touch:创建普通文件  mkdir:创建目录文件

运用ls -l:其中开头为-时普通文件;为d为目录文件;为p为管道;c,b为设备文件;

    其中分为属主(u),同组(g),其他(o)

    r:4 ;w:2 ;x:1;

    chmod:改变权限 如:chmod u+x first.c  chmod 775 first.c

cp:拷贝文件 如:普通文件cp a.txt b.txt  目录文件:cp -r tmp dir

mv:重命名或移动文件

cat:打印普通文件夹的内容(一般内荣少)如:cat first.c

more:显示大量文件夹的内容;用法同上

less:显示文件内容可以用滚轮反复看;

head:显示文件前十行

tail:显示文件后十行

前面5个退出观看可以按q

ctrl+d 结束cat输入

ctrl+c 结束进程

vim:进入普通文件夹

    set nu :显示行数  n yy :复制行数 p:贴贴 n dd:剪切,删除  u:撤销

find:查询字符串 用法:find 路径 -name '文件名‘ 如:find /home/stu -name first.c

grep:在文件夹中查找相关字符串,常与’ | '连用 用法:grep 字符串 文件名 

如:  grep "hello" first.c    grep  -i "hello" first.c 查找大小写的hello

          grep  -c "hello" first.c 查找含有“hello"的代码行数

          grep  -v "hello" first.c 查找不含hello的代码

          grep  -v -i "hello" first.c 查找不含大小写hello的代码

|(管道):如 ls /bin | grep "pwd"查找bin(命令)里有”pwd“的命令。将ls/bin的信息写入管道,在管道中找pwd若找到将其打印在屏幕上

man:显示库文件调用手册,其中1为命令;2为系统调用;3为库函数;如 man 3 printf(进入printf函数的库函数说明);

进程:ps:显示当前进程,显示进程id号,名字时间等

           ps -f:显示当前Id号,用户名,副Id号等更详细的数据

           ps -e:显示全部进程信息

           ps -ef:显示全部进程得详细信息

           sleep 300:在前端进程指令,无法进行其他命令

           sleep 300&:在后端进行指令,可以进行其他指令

           ps -ef | grep sleep:通过管道在全部指令中查找特定的指令

           kill 进程id号:结束某项指令

           在前端的指令也可以用ctrl+c来结束指令

top:查看当前任务情况(包括数量等等)按q键退出

tar: 压缩与解压 常用 c(创建一个包),v(显示创建包的过程),f(创建一个普通文件),x(释放包的内容),z(用于解压缩包)如:tar cvf first a.c b.c(将a.c与b.c放入一个文件夹中);tar xvf first(释放包的内容);gzip first(将包进行压缩);tar zxf first.gz(将压缩包进行解压缩);

分文件写程序:gcc -c a.c:将a.c文件转变为a.o文件 (可以验证是否有语法错误)

                          gcc -c b.c 最后进行 gcc -o ab a.o b.o进行链接

makefile文件:管理工程,实现自动化编译 ;vim makefile进行makefile的编写,后进行make进行自动编译;make clean可以自动清理 a.o, b.o, main

all:main

GDB=-g//加入调试信息

main:a.o b.o
    gcc -o main a.o b.o
a.o:a.c
    gcc -c a.c ${GDB}//时延make时就可以自己调试不用手动加-g
b.o:b.c
    gcc -c b.c ${GDB}
clean:
    rm -rf *.o main

调试程序:gdb工具 :1.调试的对象:exe文件  2.开发版本,发行版本:开发-->可执行程序中包含调试信息  发行-->不包含(stdin键盘 stdout屏幕)3.常见命令:l-->显示代码   l+行号-->就跳到第几行       l+文件名:1-->跳转到该文件的第一行处(如 l b.c:1)        b+行号-->加断点                    info break-->显示断点信息    r-->运行程序   n-->单步执行    p-->打印  p+&某变量(p &b)-->  可以查看变量地址   p+某变量(p b)-->  可以查看变量值     s-->进入函数     finish-->跳出函数   c-->从一个断点可以直接运行到下一个断点     bt-->显示函数调用的栈关系(即函数的包含关系,可以知道当前自己在那个函数里面,还是在主函数里面)   4.在编译代码时  gcc -o d d.c -g(其中-g为有调试信息)       5.gcc详细介绍见第四节课1:05:00

库文件:预先编译好的方法的集合(add.c-->add.o)        头文件在:/usr/include           /usr/bin(命令,二进制可执行程序)          /lib(/usr/lib):存放库文件                                               1.静态库-->会把用到的方法复制到可执行程序中(即在当前目录下可以执行,不用将文件libfoo.a移动到/lib或/usr/lib)  libc.a                                                                                                                    制作静态库:①将原文件编译生产目标文件 如a.c-->a.o          ②将目标文件打包生产库文件:如ar crv lib库名.a  库名.o 库名.o (c为建立备存文件 r为将文件插入备存文件中)    ---->gcc -o main main.c -L路径 -l库名 (如-lfoo--->libfoo.a  lib为前缀   .a为后缀 )                                             2.共享库(用的多)-->不会把用到的方法复制到可执行程序中(即需要将文件libfoo.so移动到/lib或/usr/lib)-->ldd main(显示main的共享库)  libc.so                                                                        制作动态库:①将原文件编译生产目标文件 如a.c-->a.o   ②将目标文件打包生产库文件:gcc -shared -fPIC -o lib库名.so  库名.o 库名.o  gcc -o main main.c -L路径 -l库名 ④将建好的库移动到/lib或/usr/lib中⑤./main即可运行程序                                                                                              3.ldd可以查看已经使用的共享库 (ldd+可执行文件名)                                                                  (两个库都有优先共享库)       

缓冲区:fflush(stdin/stdout/stderr)可以强制刷新,使缓冲区的内容打印到屏幕上                               exit(0);//1.刷新缓冲区  2.退出程序 _exit(0)--->头文件#include<unistd.h>                                           return 0:退出程序后系统自动调用 exit(0)后面步骤同上 

主函数参数:

#include<stdio.h>
//int argc主函数参数个数,char*argv[]传给主函数的参数内容,char*envp[]环境变量

int main(int argc,char*argv[],char*envp[])
{
    printf("argc=%d\n",argc);//int argc主函数参数个数
    
    for(int i=0;i<argc;i++)//char*argv[]传给主函数的参数内容
    {
         printf("argv[%d]=%s\n",i,argv[i]);
    }

    for(int i=0;envp[i]!=NULL;i++)//char*envp[]环境变量
    {
        printf("envp[%d]=%s\n",i,envp[i]);
    }    
    return 0;
}
//主函数传参
./main hello aca//就将hello aca传给了argv[]
//此./main中有三个参数argv[0]=./main  argv[1]=hello  argv[2]=aca

计算机五大部件:运算器,控制器(cpu中央处理器),存储器(外存与内存),输入设备(I),输出设备 (O) 系统总线:地址总线:传地址,数据总线:传递数据,控制总线:控制逻辑执行

fork:进程:一个正在运行的程序    pcb(描述进程是一个结构体,记录信息,存放进程所需的id号等等)  状态:就绪,运行,阻塞       内存管理:物理内存(1.掉电丢失数据2.访问速度快)   外部硬盘(1.数据永远存放2.掉电不丢失)      虚拟内存:假设物理内存不够,先从硬盘内借用一些内存当作物理内存来使用,访问速度没有物理内存快,但可以解决物理内存不够的情况。原理是将要运行的数据先放在内存中,将先不用的数据放在硬盘划分的区域,就可以运行比物理内存还大的程序。

 其中页表左侧为逻辑页,右侧为物理页。看物理页要有逻辑页。一个页面为4K=4x1024=4096。      写时拷贝:在修改父进程或子进程时才进行拷贝,不改变时父子进程共享页面。以页为单位

fork:复制进程(用处:1.fork复制+exec替换 2.处理任务,可以采用多线程方法)(父进程返回值为子进程的ID号,子进程的返回值为0,两者一模一样且同时进行)返回值为pid_t fork();通过判断返回值看是子进程还是父进程。                                                                                                      地址:父子进程共用一块地址空间,但存储的n值不一样,因为打印出来的是逻辑地址,不是物理地址,两者的逻辑地址是相同的但是物理地址是不同的,对于同一个进程来说逻辑地址相同则物理地址相同,但是对于两个不同的进程来说逻辑地址相同物理地址不一定相同。(nm main查询可执行文件main的地址)                                                                                                                             (见下面代码即day2/fork.c)   

 此图为逻辑地址解释图。逻辑地址就是对于起始位置的偏移量。   适用于win32(4G)不是   win64(8G)。    

#include<stdio.h>//测试fork进程
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
int main()
{
    int n=0;//循环次数
    char *s=NULL;//存放字符串
    pid_t pid=fork();//pid_t相当于int
    if(pid==-1)
    {
        exit(1);
    }    
    if(pid==0)
    {
        n=3;
        s="child";
    }   
    else
    {
        n=7;
        s="parent";
    }   
    for(int i=0;i<n;i++)
    {
        printf("s=%s curr_pid=%d ppid=%d n=%d n=%p\n",s,getpid(),getppid(),n,&n);//当前进程的id号,getpid()为获取id号,ppid为其父进程id号
        sleep(1);
    }
    exit(0);
}

 fork()相关题目:

1:#include<stdio.h>

int main()
{
    for(int i=0;i<2;i++)
    {
        fork();
        printf("A\n");//6个A
    }
}


2:#include<stdio.h>

int main()
{
    for(int i=0;i<2;i++)
    {
        fork();
        printf("A");//8个A ,会先存放在缓冲区内 fork时也会将缓冲区的A复制过去
    }
}

3:#include<stdio.h>

int main()
{
      fork()||fork();
      printf("A\n");//3个A

}

 第三题详解:

僵死进程(与fork一起用):子进程先结束,父进程没有调用wait接收它的退出码,子进程就变成僵死进程了。

#include<stdio.h>//测试fork进程
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
    int n=0;//循环次数
    char *s=NULL;//存放字符串
    pid_t pid=fork();//pid_t相当于int
    if(pid==-1)
    {
        exit(1);
    }    
    if(pid==0)
    {
        n=3;
        s="child";
    }   
    else
    {
        n=7;
        s="parent";
        //wait(NULL);//不接收返回值,只执行
        int val=0;
        wait(&val);//获取退出码
        if(WIFXITED(val))//在帮助手册中查,正常结束
        {
            printf("child exit code:%d\n",WEXITSTATUS(val));//获取退出码
        }
    }   
    for(int i=0;i<n;i++)
    {
        printf("s=%s curr_pid=%d ppid=%d n=%d n=%p\n",s,getpid(),getppid(),n,&n);//当前进程的id号,getpid()为获取id号,ppid为其父进程id号
        sleep(1);
    }
    exit(0);
}

文件描述符:fopen,fclose(库函数)|open,read,write,close(系统调用) 在内核中实现,                   open("路径+名称",r/w):文件存在   open("路径+名称",r/w,文件权限):文件不存在                     只读打开:O_RDONLY    只写打开:O_WRONLY  读写打开:O_RDWR  具体看(2)open库函数                                           

#include<fcntl.h>//write写操作
int main()
{
    int fd=open("fil.txt",O_WRONLY|O_CREAT,0600);
    //fil.txt为要打开的文件  O_WRONLY|O_CREAT为要创建一个文件并且可写  0600为八进制表示属主可读可写但是其他的不可读也不可写见chmod
    if(fd==-1)
    {
        exit(1);
    }
    write(fd,"hello",5);//在fd中写入"hello"共写入5个字节
    close(fd);
    exit(0);
}
#include<fcntl.h>
int main()//读操作,每次读完后,下一次可以接着上一次读到的地方继续读
{
    int fd=open("fil.txt",O_RDONLY,0600);
    if(fd==-1)
    {
        exit(1);
    }    
    char buff[128]={0};
    read(fd,buff,127);
    printf("buff=%s",buff);
    close(fd);
    exit(0);
}

复制操作:

#include<stdio.h>
int main(int argc,char*argv[],char*envp[])
{
    if(argc!=3)//判断变量是否为三个
    {
        printf("error argc");
        exit(1);
    }
    char*s_name=argc[1];//要读的数据
    char*t_name=argc[2];//要写的数据
    int fdr=open(s_name,O_RDONLY,0600);//打开只读文件
    int fdw=open(t_name,O_WRONLY|O_CREAT,0600);//打开只写文件
    if(fdr==-1||fdw==-1)//判断两文件是否错误
    {
        printf("open error");
        exit(1);
    }
    printf("fdr=%d fdw=%d\n",fdr,fdw);//打印fdr,fdw的值为3和4,0,1,2为文件描述符stdin等等,见下图
    char buff[1024];//存放数据
    int num=0;//表示每次读了多少字节
    while((num=read(fdr,buff,1024))>0)//将每次读到的返回到num中,若返回值大于0则继续循环
    {
        write(fdw,buff,num);//将读到的文件写入buff中
    }
    close(fdr);
    close(fdw);
    exit(0);
}

printf-->在底层就是调用write。 

系统调用与库函数的区别:

库函数在用户空间,系统调用在内核空间。当应用程序进行系统调用时,会产生中断,陷入内核,根据用户空间的系统调用号和内核空间的系统调用表,执行内核代码。应用程序可以先调用库函数再由库函数进行系统调用,也可以直接由应用程序进行系统调用。

父进程先打开一个文件后,fork后子进程是否可以共享使用:父进程打开文件后再进行fork,父子进程共享该文件描述符。//若父进程在fork后才打开文件,那么父子进程将不会共享文件,而是各自产生单独的文件。验证如下代码:

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
//
    int buff[128]={0};//父进程先将文件打开后在进行fork,父进程与子进程会共享一个文件
    int fd=open("filet.txt",O_RDONLY,0600);//filet.txt自己创建,里面存放hello
    if(fd==-1)
    {
        exit(1);
    }
//
    pid_t pid=fork();
//
    int buff[128]={0};//若父进程在fork后才打开文件,那么父子进程将不会共享文件,而是各自产生单独的文件
    int fd=open("filet.txt",O_RDONLY,0600);//filet.txt自己创建,里面存放hello
    if(fd==-1)
    {
        exit(1);
    }
//
    if(pid==-1)
    {
        exit(1);
    }
    if(pid==0)
    {
        read(fd,buff,1);
        printf("child buff=%s\n",buff);
        sleep(1);
        read(fd,buff,1);
        printf("child buff=%s\n",buff);
    }
    else
    {
        read(fd,buff,1);
        printf("parent buff=%s\n",buff);
        sleep(1);
        read(fd,buff,1);
        printf("parent buff=%s\n",buff);
    }
    close(fd);
    exit(0);
}

替换:exec:有6种:execl,exexlp,execle,execv,execvp,   execve(系统调用)   这些只是参数不同   

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>//open close read write
#include<assert.h>
int main(int argc,char*argv[],char*envp[])
{
    printf("exec pid=%d\n",getpid());//获取父进程id号

    execl("/usr/bin/ps","ps","-f",(char*)0);

    execlp("ps","ps","-f",(char*)0);//不需要写路径,只需要写要找的名称即可

    execle("/usr/bin/ps","ps","-f",(char*)0,envp);//第二个ps只是名字可以改为其他名字,这个名字不重要,但是前面路径不能错

    char *my_envp[10]={"ps","-f",0};
    execv("/usr/bin/ps",my_envp);

    char *my_envp[10]={"ps","-f",0};
    execvp("ps",my_envp);

    char *my_envp[10]={"ps","-f",0};
    execve("/use/bin/ps",my_envp,envp);//系统调用
}

创建bush:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值