2019年8月8日星期四

一. linux系统编程学习大纲

1. 进程的概念,进程诞生与死亡,进程函数接口,进程的意义。

2. 进程之间通信方式:有名管道,无名管道,信号,消息队列,共享内存,信号量

3. linux进程的信号集,设置信号的阻塞状态。

4. 线程的概念,线程与进程的区别?线程诞生与死亡,函数接口。

5. 线程的同步互斥方式,有名信号量,无名信号量,互斥锁,读写锁,条件变量

6. 线程池 -> 为了同时处理多个任务。

二. 进程的概念?

1. 什么是程序?什么是进程?

程序就是一堆待执行的代码。  -> 静态的文本数据。 例如: project.c(C语言程序) /  project(可执行程序)。

进程就是当程序被CPU加载,根据每一行代码做出相应的效果,才能形成一个动态的过程,这个过程就称之为进程。

2. 在linux下,如何开启一个新的进程?

直接在linux下执行程序即可。

例如: ./project   -> 开启一个新的进程!

3. 当进程开启,系统会为进程分配什么资源?

1)会分配进程对应内存空间。

2)任务结构体 -> struct task_struct   -> 在linux下,任何进程就像一个任务。

结构体在哪里?

Ubuntu: /usr/src/linux-headers-3.5.0-23/include/linux/sched.h

struct task_struct {

volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */  -> 进程运行状态。

void *stack;

....

struct uprobe_task *utask;

int uprobe_srcu_id;

#endif

};

三. 关于查看进程信息的linux命令。

1)查看整个linux系统的ID号  -> ps -ef(静态)

gec@ubuntu:~$ ps -ef

用户名     PID   PPID    创建时间          持续时间   进程名字

root         1     0  0 16:37    ?        00:00:00  /sbin/init          -> 祖先进程

gec       2272     1  0 16:37    ?        00:00:01  gnome-terminal      -> linux终端

gec       2278  2272  0 16:37    pts/1    00:00:00  bash         -> linux终端的子进程,叫bash进程

gec       2720  2278  0 18:54    pts/1    00:00:00  ps -ef              -> bash进程的子进程,shell命令

2)查看进程CPU使用率  -> top(动态)

gec@ubuntu:~$ top

Tasks: 150 total  -> 当前系统有150个进程

2 running     -> 2个在运行态

148 sleeping  -> 148个睡眠态

0 stopped     -> 0个暂停态

0 zombie      -> 0个僵尸态

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND

1049 root      20   0 96160  26m 6700 S  5.3  2.6   0:18.50 Xorg

S  -> state当前进程状态

%CPU -> 当前瞬间CPU占用率

%MEM -> 当前瞬间内存占用率

3)查看整个系统的关系图  -> pstree

gec@ubuntu:~$ pstree

init─┬─NetworkManager───{NetworkManager}

├─accounts-daemon───{accounts-daemon}

├─acpid

├─gnome-terminal─┬─bash───pstree

四. 进程的诞生与死亡。

1.进程有什么状态?

进程生老病死就是从进程开启到进程结束经历所有状态。

就绪态:不占用CPU资源,不运行代码。

运行态:占用CPU资源,运行代码。

暂停态:占用CPU资源,不运行代码,可以切换到就绪态/运行态

睡眠态:占用CPU资源,运行代码,可以切换到就绪态/运行态

僵尸态:占用CPU资源,不运行代码,不可以切换到就绪态/运行态

死亡态:不占用CPU资源,不运行代码。

2. 什么是占用CPU资源?

就是进程自身的资源(任务结构体)没有释放。

3. 什么是僵尸态?

进程结束时,一定会切换到僵尸态。所谓僵尸态,就是本进程已经结束,但是自身的资源还没有释放掉。

详细见:"进程的生老病死.jpg"

4. 需要注意的地方:

1)进程在暂停态时,如果收到继续的信号,是切换到就绪态,而不是运行态。

2)进程退出时,一定会变成僵尸态。

3)进程不可以没有父进程,也不能同时拥有两个父进程。

4)孤儿进程特点:当自己的父进程退出后,会马上寻找继父,而不是等到变成僵尸再找。

5)init祖先进程特点:一定会帮所有的孤儿回收资源。

五. 进程的函数接口?

单进程程序  -> 只能一行一行代码去执行。

创建子进程意义: 同时处理多个任务。

1. 在进程内部创建一个新的子进程?  -> fork()  -> man 2 fork

功能: fork - create a child process  -> 创建子进程

使用格式:

#include <unistd.h>

pid_t fork(void);

参数:无

返回值:  pid_t  -> 进程PID号数据类型  %d

成功:

父进程 -> 子进程的PID号  >0

子进程 -> 0

失败:

父进程 -> -1

没有创建出子进程。

例题: 在进程内部创建一个新的子进程,看看会不会同时处理两件事情。

#include <unistd.h>

#include <stdio.h>

int main(int argc,char *argv[])

{

/* 现在只有一个进程,就是父进程 */

printf("hello\n");

printf("world\n");

fork();

/* 到这里为止,就有两个进程 */

printf("appletree\n");

return 0;

}

结果1:  父进程先运行,子进程后执行。

gec@ubuntu:/mnt/hgfs/GZ1934/09 系统编程/01/code$ ./fork_test

hello

world

appletree  -> 父进程打印

gec@ubuntu:/mnt/hgfs/GZ1934/09 系统编程/01/code$ appletree   -> 子进程打印

结果2:  子进程先运行,父进程后执行。

gec@ubuntu:/mnt/hgfs/GZ1934/09 系统编程/01/code$ ./fork_test

hello

world

appletree  -> 子进程打印

appletree  -> 父进程打印

gec@ubuntu:/mnt/hgfs/GZ1934/09 系统编程/01/code$

结论:

1)父子进程谁先运行,是随机的。
2)fork()后的代码,两个进程都会执行。

练习1: 写一个程序,使得子进程先打印apple,父进程再打印hello。

#include <unistd.h>

#include <stdio.h>

int main()

{

/* 父进程 */

pid_t x;

x = fork();

/* 父进程 */     /* 子进程 */

//返回值情况:       x > 0          x = 0

if(x > 0)  //父进程

{

usleep(5000);

printf("hello!\n");

}

if(x == 0) //子进程

{

printf("apple!\n");

}

return 0;

}

2. 查看自身的ID号以及查看父进程的ID号

getpid()       getppid()   -> man 2 getpid

功能: getpid, getppid - get process identification  -> 获取进程的PID号

使用格式:

#include <sys/types.h>

#include <unistd.h>

pid_t getpid(void);

pid_t getppid(void);

参数:无

返回值:

getpid()

成功: 当前进程的ID号

失败: 不存在的!

getppid()

成功: 当前进程的PID号

失败: 不存在的!

练习2: 在子进程中打印自己与父进程的ID号,在父进程中打印自己与子进程的ID,通过ps -ef命令查看ID是否一致!

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

int main()

{

pid_t x;

x = fork();

if(x > 0) //父

{

usleep(10000);

printf("parent pid = %d\n",getpid());

printf("child pid = %d\n",x);

}

if(x == 0) //子

{

printf("child pid = %d\n",getpid());

printf("parent pid = %d\n",getppid());

}

return 0;

}

练习3: 验证孤儿进程会马上寻找继父,而不是等到孤儿进程结束才找。

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

int main(int argc,char *argv[])

{

pid_t x;

x = fork();

if(x > 0)

{

sleep(2);

}

if(x == 0)

{

printf("parent pid = %d\n",getppid());

sleep(3);

printf("parent pid = %d\n",getppid());

printf("helloworld!\n");

sleep(1);

printf("appletree!\n");

}

return 0;

}

六. 如何解决僵尸问题?

1. 父进程主动回收子进程的资源。  -> wait()   -> man 2 wait

功能: wait for process to change state

使用格式:

#include <sys/types.h>

#include <sys/wait.h>

pid_t wait(int *status);

status:储存子进程退出状态的指针。

填NULL,代表父进程不关心子进程的退出状态。

不填NULL,代表父进程想知道子进程的退出状态。

返回值:

成功: 退出的子进程的ID号

失败: -1

练习4: 验证wait()可以帮子进程回收资源。

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

#include <sys/wait.h>

int main()

{

pid_t x;

x = fork();

if(x > 0)

{

sleep(10);  //有1个僵尸

wait(NULL);  //僵尸态 -> 死亡态

sleep(8);  //有0个僵尸

}

if(x == 0)

{

printf("hello!\n");  //运行态 -> 僵尸态

}

return 0;

}

2. 父进程还在,但是不主动调用wait()去回收资源。

举例子。

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

int main()

{

pid_t x;

x = fork();

if(x == 0)

{

printf("parent pid = %d\n",getppid());

printf("child helloworld!\n");

//printf("parent pid = %d\n",getppid());

} //子进程: 运行态 -> 僵尸态

if(x > 0)

{

sleep(15); //1个僵尸态

printf("parent helloworld!\n");

sleep(3);

printf("parent exit!\n");  //子进程就会寻找继父,帮自己回收资源。

}

return 0;

}

3. 父进程比子进程先退出,子进程就会马上寻找继父,等待自身变成僵尸态时,就会让继父帮自己收尸!

举例子。

#include <stdio.h>

#include <sys/types.h>

#include <unistd.h>

int main(int argc,char *argv[])

{

pid_t x;

x = fork();

if(x > 0)

{

sleep(2);

}

if(x == 0)

{

printf("parent pid = %d\n",getppid());

sleep(3);

printf("parent pid = %d\n",getppid());

printf("helloworld!\n");

sleep(10);   -> 在这10秒内,子进程继父就是祖先进程。

printf("appletree!\n");

-> 子进程结束,让继父帮子进程回收资源。

}

return 0;

}

七. 进程的退出

exit()   -> 查询: man 3 exit

exit()函数特点:清洗缓冲区的数据,再退出!

使用格式:

#include <stdlib.h>

void exit(int status);

status: 退出的状态

0  -> 正常退出

非0 -> 异常退出

返回值:无。

_exit()  -> 查询: man 2 _exit

_Exit()  -> 查询: man 2 _Exit

_exit()与_Exit是一样的,特点就是不清洗缓冲区数据,直接退出!

#include <unistd.h>

void _exit(int status);

#include <stdlib.h>

void _Exit(int status);

status: 退出的状态

0  -> 正常退出

非0 -> 异常退出

返回值:无。

1. 缓冲区问题。

#include <stdlib.h>

#include <stdio.h>

#include <unistd.h>

int main()

{

printf("hello");

exit(0); //输出hello,再退出!

_exit(0); //不输出hello,直接退出!

printf("world"); //无论什么退出函数,都不会运行到这里。

return 0;

}

2. 进程退出状态。   -> 只要程序中调用exit()/_exit(),都一定会从运行态变成僵尸态。

#include <stdlib.h>

#include <stdio.h>

#include <unistd.h>

#include <sys/wait.h>

int main()

{

pid_t x;

int state;

x = fork();

if(x > 0)

{

wait(&state);

printf("state = %d\n",state);

}

if(x == 0)

{

sleep(5);

exit(0); //这个exit(0)只是说明子进程退出。

}

return 0;

}

3. exit()与return区别?

举例子。

void fun()

{

//return;  -> 效果:就会打印hello

exit(0);   -> 效果:不会打印hello

}

int main()

{

fun();

printf("hello!\n");

return 0;

}

结论:

return  -> 只是代表函数的结束,返回到函数调用的地方。
exit()  -> 代表整个进程的结束,无论当前执行到哪一行代码,只要遇到exit(),这个进程就会马上结束!

八. 从内存角度分析父子进程资源问题。

举例子。

#include <stdlib.h>

#include <stdio.h>

#include <unistd.h>

#include <sys/wait.h>

int main(int argc,char *argv[])

{

int a = 100;

pid_t x;

x = fork();

if(x > 0)

{

//int a = 100;

sleep(1);

printf("parent a = %d\n",a); //100

}

if(x == 0)

{

a = 50;

printf("child a = %d\n",a); //50

}

return 0;

}

结论:

1)fork()之后,父进程会复制一份几乎与父进程一模一样的资源给子进程(PID号除外)

2)父子进程拥有独立的空间,在其中一个进程中修改数据,不会影响到另外一个进程的数据。

九. exec函数族接口。 -> man 3 execl

#include <unistd.h>

int execl(const char *path, const char *arg, ...);

path: 需要执行的那个程序的名字,例如: /home/gec/project

arg: 需要运行时传递的参数,例如: "project","aaa",NULL

返回值:

成功: 非-1

失败: -1

例子: 产生一个子进程,让子进程执行"ls -l"这个程序。

#include <stdlib.h>

#include <stdio.h>

#include <unistd.h>

#include <sys/wait.h>

int main(int argc,char *argv[])

{

pid_t x;

x = fork();

if(x > 0)

{

sleep(2);

printf("I am parent!\n");

}

if(x == 0)

{

printf("apple tree!\n");

execl("/bin/ls","ls","-l",NULL);

printf("helloworld!\n");  -> exec函数族替换掉一个程序,子进程之后的代码都不会执行。

}

return 0;

}

补充:在GEC6818平台播放mp3歌曲命令

[root@GEC6818 /]#madplay jay.mp3

MPEG Audio Decoder 0.15.2 (beta) - Copyright (C) 2000-2004 Robert Leslie et al.

Title: ····

Artist: ···

Album: ········

转载于:https://www.cnblogs.com/zjlbk/p/11322760.html

2019年8月8日星期四(系统编程)相关推荐

  1. 2019年8月1日星期四(数据结构)

    2019年8月1日星期四 一. 双向链表与双向循环链表区别? 1. 双向循环链表最后一个节点的后继指向头节点,头节点的前驱指针指向最后一个节点. 2. 节点模型? struct list_node{ ...

  2. 2019年7月4日 星期四 今日计划

    2019年7月4日 星期四 今日计划 学习自定义事件 总结自定义事件 预期进度80%

  3. “尊人有分而敬人有度”.相干的探讨之壹-2019年7月25日 星期四

    本文取材于"Assortedpoetry review";标题是"尊人有分,敬人有度".正文由" 原野先生"诵読(请点此听看己亥年陸月荟萃听 ...

  4. 2019年9月22日vivo笔试编程题第二题java实现

    题目大概描述:输入两个数n,m用空格隔开,一共有n个人,依次报数,当报到m的倍数时出列并记录他的初始位置,用空格隔开. 输入:6 3 输出:3 6 4 2 5 1 小白拙见 import java.u ...

  5. 300英雄11月服务器维护,《300英雄》【公告】2019年11月14日06:00-09:00全区停机更新公告...

    2019年11月14日06:00-09:00全区停机更新公告 尊敬的<300英雄>玩家: <300英雄>将定于2019年11月14日06:00-09:00(星期四),对所有大区 ...

  6. D2 日报 2019年6月11日

    ? 开源项目 ➡️ sfyc23/EverydayWechat watch 34 star 1690 fork 317 每日自动给女朋友发微信暖心话. github.com ➡️ YMFE/yapi ...

  7. 2019年1月14日【第一天正式学习】

    2019年1月14日星期一 任务一.把 elfpass 拷贝进 seed 虚拟机,设成 root 所有 suid 程序,用普通用户去攻击获得 root权限.可以先静态分析,搞不定再用 gdb 动态调试 ...

  8. D2 日报 2019年4月17日

    ? 新闻 ➡️ Is React Translated Yet? ¡Sí! Sim! はい! react 文档翻译了多种语言 reactjs.org ? 开源项目 ➡️ formal/packages ...

  9. SiteServer CMS 新版本 V6.11(2019年7月1日发布)

    欢迎来到 SiteServer CMS V6.11版本(.NET CORE V7.0预览版本将推迟至2019年9月1日发布),经过两个月的连续迭代开发,V6.11 版本新增了采集插件以及多项BUG修复 ...

最新文章

  1. bat 将war文件转换成ear文件
  2. 交换机和路由器有哪些区别?
  3. golang中的delve
  4. 阮一峰react demo代码研究的学习笔记 - demo7 debug - how ref node is attached
  5. 工作中常用的 6 种设计模式!
  6. [秘技]解决QQ音乐超出服务区域问题
  7. avocado自动化测试框架
  8. 数据结构之栈与递归的实现及应用(斐波拉契数列递归解法和strlen递归解法)
  9. python super 多重继承_解决python super()调用多重继承函数的问题
  10. 通过IO流下载Excel文件
  11. Ubuntu开启root账户ssh远程登录
  12. OO第二次课程总结分析
  13. 将Ext JS 5应用程序导入Web项目以及实现本地化
  14. html5 canvas带音效的新年烟花特效,真的好看极了
  15. easydarwin ffmpeg
  16. 论文专利博客写作总结
  17. Linux 监控工具之Cacti使用详解(一)
  18. Windows VScode Linter pylint is not installed
  19. 本周言论 之 C2C模式
  20. Oracle具体表赋权给某用户

热门文章

  1. 全球5G手机最新排名!
  2. 如何买入期货合约(如何买入期货合约交易)
  3. 假定某计算机的CPU主频为80 MHz,CPI为4,并且平均每条指令访存1.5
  4. OLED显示屏驱动程序
  5. hashcat 使用
  6. “阿里云之父”王坚:硅谷不应当成为我们的天花板 | 腾讯2017年Q3营收同比增61%
  7. UP Meta—Web3.0世界创新型元宇宙金融协议
  8. COC建筑拖动的实现
  9. 老男孩读PCIe之四:TLP类型
  10. 衢州服务器维修,衢州市服务器费用