免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: pmerofc
打印 上一主题 下一主题

[C] C语言可以直接对硬件进行操作吗? [复制链接]

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
11 [报告]
发表于 2012-10-25 09:09 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
12 [报告]
发表于 2012-10-25 09:11 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
13 [报告]
发表于 2012-10-25 09:13 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
14 [报告]
发表于 2012-10-25 09:18 |只看该作者
这个取决于何为直接,何为硬件
不然,汇编也不能直接操作硬件,必须经过编译,呵呵

论坛徽章:
0
15 [报告]
发表于 2012-10-25 09:21 |只看该作者
本帖最后由 FaintKnowledge 于 2012-10-25 09:23 编辑

请教发表意见的几位:系统调用的read write,open,ioctl这些函数是做什么用的呢?这些函数不算C语言的范畴吗?
而且,这些函数是可以对硬件进行读写的,只是需要硬件提供一些个命令,然后使用ioctl调用这些命令.这样算不算是对硬件直接进行读写呢?
或者LZ说的是不使用硬件提供的命令,而是自己直接操作硬件??这个不得有什么爆什么啊?得有多少才够浪费的 啊

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
16 [报告]
发表于 2012-10-25 09:30 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
17 [报告]
发表于 2012-10-25 09:31 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
18 [报告]
发表于 2012-10-25 09:32 |只看该作者
回复 11# pmerofc


    我以前也这么觉得,不过学了汇编才发现,汇编也是碰不到硬件的= =|||

现代的CPU都分“保护模式”和“实模式”,有一些很重要的指令,比如说设置一些关键的寄存器这些事情,是保护模式的程序干不了的。你干了CPU也会掠过去。比如说设置中断向量表指针这种事情。

所谓操作硬件,分两部分:

1. 在物理上,一段地址属于某个硬件,写入或读出这个地址的内容,来操作硬件。
2. 当硬件来消息了,会通知CPU产生一个“中断“,如何处理这个中断,由中断向量表对应项指向的函数决定。

通常电脑启动是这么开始的:
1. 启动的时候BIOS决定各个硬件的中断号。(软跳线)
2. 每个中断号可能能对应多个硬件,即所谓的”总线“,比如著名的USB(通用串行总线),这时,CPU负责联络的就不是硬件本身,而是所谓”硬件控制器“。
3. 所以,起电以后,电脑进入实模式,BIOS负责找到能启动的存储硬件,读取这些硬件的前某些字节,载入内存的前某些位置,然后CPU IP指针设置为那个值,开始执行程序。
4. 这段程序还不是操作系统,只是一个引导器,引导器负责找到内核所在地,然后将内核载入内存,跳转到内核入口开始执行。
5. 内核初始化向量表(用自己内部已经实现的一堆函数),然后设置向量表指针。初始化内存分页机制,然后初始化页表指针等等。所有初始化工作做完,启动第一个进程,通常是init。
6. init进入保护模式,开始执行程序,进入用户眼中的“操作系统”。

也就是说,操作系统是个“盒子”,利用时间上的优先便利,将其他所有程序包进去,保证所有程序都无法(在CPU级别上)触发硬件。

当一个硬件消息到来的时候——比如你碰了一下你的USB鼠标,过程是这样的:
1. 鼠标向USB总线控制器发送一个消息。
2. 总线控制器根据这个消息,给鼠标总线的控制权。(通常这个控制权是分时的,就是你只能用多久,过了就剥夺你的使用权,得重新申请)
3. 鼠标利用这个权利,向总线发出事件通知。
4. 总线控制器先收到了这个通知,根据通知,设定自己的某几个寄存器,然后向中断仲裁器发送消息。
5. 中断仲裁器在处理完自己的工作以后,向CPU发送消息(一个特殊的针脚的电平被改变)
6. CPU处理完自己的事情以后(通常是完整地完成一条机器指令以后),例行检查中断电平,发现被改变,则CPU内部触发中断。
7. 这个触发导致当前执行的任何进程被中断,CPU陷入内核特权级别。内核的中断向量接管现场。
8. 内核在当前的进程的内核栈上干活(这就是为什么说写中断处理例程不要假设自己所在进程的原因:自己有可能在任何进程的上下文下执行)。
9. 内核把紧要的事情做完,然后做个记录,就退出了中断例程——因为中断例程CPU很脆弱,啥都不能干得眼巴巴地等着,所以这货越短越好。
10. 当前进程毫无所觉地做完自己该做的事情。
11. 当前时钟tick到来,CPU暂停所有正在做的事情,开始处理内核事务,内核tick中断例程被执行。
12. 内核例行地检查所有记录,继续执行那些耗时的操作。这时,内核分析之前保存下来的USB的状态,然后开始从地址映射里读出鼠标的当前状态。
13. 这个状态被写入一个“普通”的文件,这个文件就是/dev/mouse
14. 这个写入导致一切跟这个文件有关的状态被改变,一些事件被执行,确切地说,跟踪这个文件的进程会得到“这个文件被改变”的通知。
15. 内核退出tick例程,继续执行当前的进程,直到下个tick的到来,这时内核发现当前进程的时间片用完,接着内核调度进程。
16. 进程调度到了使用/dev/mouse的那个进程(通常是图形服务器,X Server),那个进程得到执行,检查/dev/mouse文件(或者直接被这个文件通知),发现鼠标改变,执行根窗口的鼠标改变例程,首先重绘鼠标指针,然后找到鼠标的当前位置,然后一层一层向下最终找到这鼠标所在窗口,向那个窗口发送IPC消息。
17. 进程调度到那个窗口,窗口得到IPC消息,窗口开始回调鼠标事件,一层一层又一层,最后开始执行鼠标处理例程。
18. 窗口鼠标处理例程发现鼠标实际上什么都没干,扔了这个消息
19. 一切照旧………………

你想到啥了?低效无能的官府机构?对了,就是这样的………………你觉得在这个官僚主义的地方,你还能直接操纵硬件?别想了…………

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
19 [报告]
发表于 2012-10-25 09:43 |只看该作者
回复 18# starwing83


    厉害!对系统了解的很透彻!再说说程序调用 fwrite 写磁盘文件,发生了什么事情呢?
搬凳子学习。。。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
20 [报告]
发表于 2012-10-25 10:04 |只看该作者
回复 19# 群雄逐鹿中原


    fwrite啊?这个就简单多了…………

1. fwrite将内容写到缓冲区,除非满了,否则立即返回
2. 缓冲区满,fwrite在内部调用write系统调用。
3. write系统调用陷入内核,根据内核i-node相关信息,找到对应的那个ops,调用ops->write
4. 通常这是个file-system类型的driver,它通常只是负责将buffer从用户态拷贝到内核态,串到buffer的列表里面。
5. 除非flush了,否则事情就这么完了。
6. 到flush了,内核发现事情大条了,一时间搞不好了,就让那个进程睡掉,然后内核继续施施然爱做啥做啥。
7. 等到内核终于想到了有这茬事儿(其实每次都能想到,tick的时候肯定会处理),内核找到对应的存储driver,让他负责处理同步问题。
8. 存储driver——这里就假设是硬盘吧,闪存稍微有点不太一样——对内存中维护的所有buffer进行排队,然后划分具体的块,按照一定的顺序,启动DMA。这个排队就是传说中的电梯调度算法了——别看我,我也不知道。
9. DMA大师出马,这货很牛逼的,实现方式可能不太一样,反正总的来说就是在CPU累死累活苟延残喘的瞬间,偷偷的一块一块地把内存里的数据转移出去,目标:硬盘的缓冲区。
10. DMA首先PCI总线,PCI控制器联系IDE控制器,IDE询问硬盘控制器,硬盘控制器检查硬盘状态(其实是检查硬盘缓冲区状态),一切OK以后反过来顺次向上通知,最后通知到达DMA里。
11. DMA将数据块通过总线传递,数据块进入硬盘缓冲区,一般到这里系统能做的事情就都就完了。DMA通过中断仲裁器通知CPU事儿完了,接下来的冗长过程参见上贴,总的来说就是事儿做完了,根据调度策略,那个被强制睡眠的进程被唤醒继续执行,或者很可怜地被放到调度队列里等待下次被调度。
12. 硬盘控制器维护缓存(通常较小,8M~32M左右),缓存如果满了,就负责控制硬盘,将缓存写入硬盘。
13. 硬盘控制器控制电机,让磁头旋转到对应磁道表面,根据每圈的一个特殊的信号同步。
14. 同步完毕,计算好大概能到那个位置的时间,然后掐好表,发射!
15. 再转到那个地方,磁头读取一下检查一下,恩,对头,然后继续写下个块……

中间省了一大块,DMA到硬盘缓冲中间一堆事儿,DMA做完事儿了通知上层驱动也是一堆事,都写了20条就写不完了,大致上就是这样,配合上一贴应该很容易理解吧……
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP