ASOC注册过程

一、什么是ASOC

在嵌入式系统里面的声卡驱动为ASOC(ALSA System on Chip) ,它是在ALSA 驱动程序上封装的一层,分为3大部分,Machine,Platform和Codec ,三部分的关系如下图所示:其中Machine是指我们的开发板,Platform是指Soc,而Codec是指编解码器(如uda1341)

二、嵌入式系统声卡注册过程

这里我们以mini2440开发板为例 

安装新驱动insmod alsa/driver/myalsa/platform/s3c2440_iis.ko 
insmod alsa/driver/myalsa/platform/s3c2440_dma.ko 
insmod alsa/driver/myalsa/codec/uda1341.ko 
insmod alsa/driver/myalsa/machine/s3c2440_uda1341.ko 

首先我们往内核安装我们写好的声卡驱动(Machine部分的ko文件一定要放在最后面,Platform和Codec 则无特殊要求,下面会讲为什么)

1.platform部分

1.1 cpu_dai

 安装s3c2440_iis.ko的时候会注册平台驱动s3c24xx_iis_driver,因为内核中有名字同为"s3c24xx-iis"的平台设备,所以调用了对应的probe函数s3c24xx_iis_dev_probe,该函数最终会把s3c24xx_i2s_dai(cpu_dai硬件操作相关)放入链表dai_list,并命名为"s3c24xx-iis"(后面Machine驱动根据这个名字来实例化声卡)

1. platform:
1.1 s3c24xx-i2s.c : 把s3c24xx_i2s_dai放入链表dai_list, .name = "s3c24xx-iis",
s3c24xx_iis_dev_probesnd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai);list_add(&dai->list, &dai_list);
平台驱动
static struct platform_driver s3c24xx_iis_driver = {.probe  = s3c24xx_iis_dev_probe,.remove = s3c24xx_iis_dev_remove,.driver = {.name = "s3c24xx-iis",.owner = THIS_MODULE,},
};平台设备
struct platform_device s3c_device_iis = {.name		  = "s3c24xx-iis",.id		  = -1,.num_resources	  = ARRAY_SIZE(s3c_iis_resource),.resource	  = s3c_iis_resource,.dev              = {.dma_mask = &s3c_device_iis_dmamask,.coherent_dma_mask = 0xffffffffUL}
};
static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {.trigger	= s3c24xx_i2s_trigger,.hw_params	= s3c24xx_i2s_hw_params,.set_fmt	= s3c24xx_i2s_set_fmt,.set_clkdiv	= s3c24xx_i2s_set_clkdiv,.set_sysclk	= s3c24xx_i2s_set_sysclk,
};//cpu_dai相关的硬件操作
static struct snd_soc_dai_driver s3c24xx_i2s_dai = {.probe = s3c24xx_i2s_probe,.suspend = s3c24xx_i2s_suspend,.resume = s3c24xx_i2s_resume,.playback = {.channels_min = 2,.channels_max = 2,.rates = S3C24XX_I2S_RATES,.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},.capture = {.channels_min = 2,.channels_max = 2,.rates = S3C24XX_I2S_RATES,.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},.ops = &s3c24xx_i2s_dai_ops,
};

1.2 platform_dma

安装s3c2440_dma.ko时,把samsung_asoc_platform放入了链表platform_list,并命名为"samsung-audio"(后面Machineko驱动根据这个名字来实例化声卡)

1.2 sound/soc/samsung/dma.c : 把samsung_asoc_platform放入了链表platform_list, .name = "samsung-audio",
samsung_asoc_platform_probesnd_soc_register_platform(&pdev->dev, &samsung_asoc_platform);list_add(&platform->list, &platform_list);
static struct snd_pcm_ops dma_ops = {.open		= dma_open,.close		= dma_close,.ioctl		= snd_pcm_lib_ioctl,.hw_params	= dma_hw_params,.hw_free	= dma_hw_free,.prepare	= dma_prepare,.trigger	= dma_trigger,.pointer	= dma_pointer,.mmap		= dma_mmap,
};
//cpu_dam相关的硬件操作
static struct snd_soc_platform_driver samsung_asoc_platform = {.ops		= &dma_ops,.pcm_new	= dma_new,.pcm_free	= dma_free_dma_buffers,
};

2. codec注册部分

安装uda1341.ko 时,把soc_codec_dev_uda134x和uda134x_dai分别放入dai_list和codec_list链表(用于后面的Machineko驱动实例化声卡)

2. codec: uda134x.c
uda134x_codec_probesnd_soc_register_codec(&pdev->dev,&soc_codec_dev_uda134x, &uda134x_dai, 1);struct snd_soc_codec *codec;codec->driver = codec_drv; = &soc_codec_dev_uda134xsnd_soc_register_dais(dev, dai_drv, num_dai); // uda134x_dailist_add(&dai->list, &dai_list); : 把uda134x_dai放入了链表dai_listlist_add(&codec->list, &codec_list); 把soc_codec_dev_uda134x放入了链表codec_list
//设置codec芯片的硬件操作
static struct snd_soc_codec_driver soc_codec_dev_uda134x = {.probe =        uda134x_soc_probe,.remove =       uda134x_soc_remove,.suspend =      uda134x_soc_suspend,.resume =       uda134x_soc_resume,.reg_cache_size = sizeof(uda134x_reg),.reg_word_size = sizeof(u8),.reg_cache_default = uda134x_reg,.reg_cache_step = 1,.read = uda134x_read_reg_cache,.write = uda134x_write,.set_bias_level = uda134x_set_bias_level,
};

 

static struct snd_soc_dai_ops uda134x_dai_ops = {.startup	= uda134x_startup,.shutdown	= uda134x_shutdown,.hw_params	= uda134x_hw_params,.digital_mute	= uda134x_mute,.set_sysclk	= uda134x_set_dai_sysclk,.set_fmt	= uda134x_set_dai_fmt,
};//codec_dai相关的硬件操作
static struct snd_soc_dai_driver uda134x_dai = {.name = "uda134x-hifi",/* playback capabilities */.playback = {.stream_name = "Playback",.channels_min = 1,.channels_max = 2,.rates = UDA134X_RATES,.formats = UDA134X_FORMATS,},/* capture capabilities */.capture = {.stream_name = "Capture",.channels_min = 1,.channels_max = 2,.rates = UDA134X_RATES,.formats = UDA134X_FORMATS,},/* pcm operations */.ops = &uda134x_dai_ops,
};

3. machine部分

machine部分内容很多,总的调用过程如下:

s3c24xx_uda134x_probes3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1);platform_set_drvdata(s3c24xx_uda134x_snd_device, &snd_soc_s3c24xx_uda134x);     platform_device_add(s3c24xx_uda134x_snd_device);.....soc_probesnd_soc_register_card(card);  // card = &snd_soc_s3c24xx_uda134xcard->rtd = devm_kzalloc(card->dev,...card->rtd[i].dai_link = &card->dai_link[i];  // &s3c24xx_uda134x_dai_linklist_add(&card->list, &card_list);snd_soc_instantiate_cards();  // 实例化声卡snd_soc_instantiate_card(card);3.1   /* bind DAIs */for (i = 0; i < card->num_links; i++)soc_bind_dai_link(card, i);3.1.1 /* find CPU DAI */rtd->cpu_dai = cpu_dai; = //&s3c24xx_i2s_dai3.1.2 /* find_codec */rtd->codec = codec;  = // codec, codec->driver=&soc_codec_dev_uda134x3.1.3 /* find CODEC DAI */      rtd->codec_dai = codec_dai; // = &uda134x_dai3.1.4 /* find_platform */rtd->platform = platform; // = &samsung_asoc_platform3.2 /* initialize the register cache for each available codec */ret = snd_soc_init_codec_cache(codec, compress_type);3.3 snd_card_createerr = snd_ctl_create(card);static struct snd_device_ops ops = {.dev_free = snd_ctl_dev_free,.dev_register =	snd_ctl_dev_register,.dev_disconnect = snd_ctl_dev_disconnect,};snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops);dev->ops = ops;3.4 /* early DAI link probe */soc_probe_dai_link    /* probe the cpu_dai *//* probe the CODEC *//* probe the platform *//* probe the CODEC DAI *//* create the pcm */ret = soc_new_pcm(rtd, num);struct snd_pcm_ops *soc_pcm_ops = &rtd->ops;soc_pcm_ops->open	= soc_pcm_open;soc_pcm_ops->close	= soc_pcm_close;soc_pcm_ops->hw_params	= soc_pcm_hw_params;soc_pcm_ops->hw_free	= soc_pcm_hw_free;soc_pcm_ops->prepare	= soc_pcm_prepare;soc_pcm_ops->trigger	= soc_pcm_trigger;soc_pcm_ops->pointer	= soc_pcm_pointer;snd_pcm_newstatic struct snd_device_ops ops = {.dev_free = snd_pcm_dev_free,.dev_register =	snd_pcm_dev_register,.dev_disconnect = snd_pcm_dev_disconnect,};err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)dev->ops = ops;pcm->private_data = rtd;3.5 snd_card_registersnd_device_register_allerr = dev->ops->dev_register(dev)调用前面snd_pcm_new的snd_pcm_dev_registersnd_pcm_dev_registererr = snd_register_device_for_dev(devtype, pcm->card,pcm->device,&snd_pcm_f_ops[cidx],pcm, str, dev);

安装s3c2440_uda1341.ko时,注册平台驱动s3c24xx_uda134x_driver,因为内核中有同名的平台设备mini2440_audio,所以调用了s3c24xx_uda134x_probe函数

//平台驱动
static struct platform_driver s3c24xx_uda134x_driver = {.probe  = s3c24xx_uda134x_probe,.remove = s3c24xx_uda134x_remove,.driver = {.name = "s3c24xx_uda134x",.owner = THIS_MODULE,},
};//平台设备
static struct platform_device mini2440_audio = {.name		= "s3c24xx_uda134x",.id		= 0,.dev		= {.platform_data	= &mini2440_audio_pins,},
};

①s3c24xx_uda134x_probe函数调用platform_set_drvdata把snd_soc_card结构体snd_soc_s3c24xx_uda134x(含有dai_link:用来负责连接Platform
和Codec,实例化的时候会用到)保存在pdev(platform_device)->dev->p->driver_data中
,然后platform_device_add(s3c24xx_uda134x_snd_device),因为内核中有同名的平台驱动soc_driver,所以调用该驱动的probe函数(soc_probe函数)

    s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1);platform_set_drvdata(s3c24xx_uda134x_snd_device, &snd_soc_s3c24xx_uda134x); dev_set_drvdata(&pdev->dev, data);dev->p->driver_data = data;    platform_device_add(s3c24xx_uda134x_snd_device);
//指定了platform和codec
static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {.name = "UDA134X",.stream_name = "UDA134X",.codec_name = "uda134x-codec",.codec_dai_name = "uda134x-hifi",.cpu_dai_name = "s3c24xx-iis",.ops = &s3c24xx_uda134x_ops,.platform_name	= "samsung-audio",
};static struct snd_soc_card snd_soc_s3c24xx_uda134x = {.name = "S3C24XX_UDA134X",.dai_link = &s3c24xx_uda134x_dai_link,.num_links = 1,        //只有1个dai_link
};
/* ASoC platform driver */
static struct platform_driver soc_driver = {.driver		= {.name		= "soc-audio",.owner		= THIS_MODULE,.pm		= &snd_soc_pm_ops,},.probe		= soc_probe,.remove		= soc_remove,
};

②soc_probe函数调用platform_get_drvdata函数把第①步的snd_soc_card结构体snd_soc_s3c24xx_uda134x(含有dai_link:用来负责连接Platform和Codec,实例化的时候会用到)取出来,然后调用snd_soc_register_card函数注册它。

soc_probestruct snd_soc_card *card = platform_get_drvdata(pdev);return dev->p->driver_data;snd_soc_register_card(card);  // card = &snd_soc_s3c24xx_uda134x

③snd_soc_register_card函数取出snd_soc_card结构体的dai_link(snd_soc_s3c24xx_uda134x结构体只有一个dai_link,这里的for只执行一次),然后调用snd_soc_instantiate_cards函数实例化声卡,其实就是根据snd_soc_s3c24xx_uda134x结构体里面的dai_link指定的名字,在dai_list、platform_list、codec_list链表找到我们之前platform和codec注册部分放入队列的那四个结构体。(soc_bind_dai_link函数逐个扫描这三个链表,根据card->dai_link[]中的名称进行匹配,匹配后把相应的codec,dai和platform实例赋值到(snd_soc_card)card->rtd[]中(snd_soc_pcm_runtime)。经过这个过程后,snd_soc_pcm_runtime:(card->rtd)中保存了本Machine中使用的Codec,DAI和Platform驱动的信息)

snd_soc_register_cardcard->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) *(card->num_links + card->num_aux_devs),GFP_KERNEL);for (i = 0; i < card->num_links; i++)card->rtd[i].dai_link = &card->dai_link[i];list_add(&card->list, &card_list);snd_soc_instantiate_cards();snd_soc_instantiate_card(card);soc_bind_dai_link(card, i);/* find CPU DAI */rtd->cpu_dai = cpu_dai; = //&s3c24xx_i2s_dai/* find_codec */rtd->codec = codec;  = // codec, codec->driver=&soc_codec_dev_uda134x/* find CODEC DAI */      rtd->codec_dai = codec_dai; // = &uda134x_dai/* find_platform */rtd->platform = platform; // = &samsung_asoc_platform

④调用传统ALSA声卡驱动的API,snd_card_create函数,该函数再调用snd_ctl_create,snd_ctl_create函数调用snd_device_new把snd_device_ops结构体ops填充到snd_device的ops成员(dev->ops = ops;),然后把snd_device挂到(snd_card)card->devices链表中。后面第⑧步snd_card_register的时候会用到snd_device_ops结构体的dev_register成员。目前我们只是先把它挂在一个链表中,如下图:

            3.3 snd_card_createerr = snd_ctl_create(card);static struct snd_device_ops ops = {.dev_free = snd_ctl_dev_free,.dev_register =	snd_ctl_dev_register,.dev_disconnect = snd_ctl_dev_disconnect,};snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops);dev->ops = ops;

⑤soc_probe_dai_link函数先是调用前面第三步找出来的cpu_dai等的probe函数(例如:s3c24xx_i2s_dai结构体的s3c24xx_iis_dev_probe),说白了就是硬件初始化。然后调用soc_new_pcm。

soc_probe_dai_link    /* probe the cpu_dai */ret = cpu_dai->driver->probe(cpu_dai);/* probe the CODEC */ret = soc_probe_codec(card, codec);/* probe the platform */ret = platform->driver->probe(platform);/* probe the CODEC DAI */ret = codec_dai->driver->probe(codec_dai);/* create the pcm */ret = soc_new_pcm(rtd, num);

⑥soc_new_pcm函数函数先是给card->rtd->ops结构体里的函数指针赋值(APP调用的程序的过程中会通过这些函数再去调用到硬件相关的函数(如前面platform的s3c24xx_i2s_dai)),然后把card->rtd->ops的地址赋给substream->ops。最后调用snd_pcm_new。

ret = soc_new_pcm(rtd, num);struct snd_pcm_ops *soc_pcm_ops = &rtd->ops;soc_pcm_ops->open	= soc_pcm_open;soc_pcm_ops->close	= soc_pcm_close;soc_pcm_ops->hw_params	= soc_pcm_hw_params;soc_pcm_ops->hw_free	= soc_pcm_hw_free;soc_pcm_ops->prepare	= soc_pcm_prepare;soc_pcm_ops->trigger	= soc_pcm_trigger;soc_pcm_ops->pointer	= soc_pcm_pointer;snd_pcm_newsnd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, soc_pcm_ops);substream->ops = ops;
或snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, soc_pcm_ops);substream->ops = ops;

⑦snd_pcm_new是传统的ALSA声卡驱动API,这一步和第④步是相似的,区别在于第④步对应的是snd_control,这里是snd_pcm的。snd_pcm_new执行完又回到soc_new_pcm函数的,这里有一个(snd_pcm)pcm->private_data = rtd;后面我们APP调用程序的时候会从pcm->private_data取出rtd(rtd里有对应我们开发板的cpu_dai、codec_dai...)

snd_pcm_newstatic struct snd_device_ops ops = {.dev_free = snd_pcm_dev_free,.dev_register =	snd_pcm_dev_register,.dev_disconnect = snd_pcm_dev_disconnect,};err = snd_device_new(card, SNDRV_DEV_PCM, pcm, &ops)dev->ops = ops;pcm->private_data = rtd;

⑧snd_card_register,该函数会调用前面第④、⑦步的snd_ctl_dev_register和snd_pcm_dev_register(通过snd_device_register_all()注册所有挂在该声卡下的逻辑设备,snd_device_register_all()实际上是通过snd_card的devices链表,遍历所有的snd_device,并且调用snd_device的ops->dev_register()来实现各自设备的注册的),这两个函数也是传统的ALSA声卡的API,它们最后都会调用到snd_register_device_for_dev函数,将snd_ctl_f_ops、snd_pcm_f_ops作为snd_register_device_for_dev的参数被传入,并被记录在snd_minors[minor]中的字段f_ops中,并创建设备节点(device_create(class_create则是在sound_core.c中))。用户程序需要打开control、pcm设备时,驱动程序通过snd_minors[]全局数组和此设备号,可以获得snd_ctl_f_ops、snd_pcm_f_ops结构中的各个回调函数(在另外一篇文章里介绍)

3.5 snd_card_registersnd_device_register_allerr = dev->ops->dev_register(dev)调用前面snd_ctl_create的snd_ctl_dev_register和snd_pcm_new的snd_pcm_dev_registersnd_ctl_dev_registersnd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,&snd_ctl_f_ops, card, name)snd_register_device_for_devpreg->type = type;preg->card = card ? card->number : -1;preg->device = dev;preg->f_ops = f_ops;preg->private_data = private_data;snd_minors[minor] = preg;preg->dev = device_create(sound_class, device, MKDEV(major, minor),private_data, "%s", name);和snd_pcm_dev_registererr = snd_register_device_for_dev(devtype, pcm->card,pcm->device,&snd_pcm_f_ops[cidx],pcm, str, dev);
static const struct file_operations snd_ctl_f_ops =
{.owner =	THIS_MODULE,.read =		snd_ctl_read,.open =		snd_ctl_open,.release =	snd_ctl_release,.llseek =	no_llseek,.poll =		snd_ctl_poll,.unlocked_ioctl =	snd_ctl_ioctl,.compat_ioctl =	snd_ctl_ioctl_compat,.fasync =	snd_ctl_fasync,
};const struct file_operations snd_pcm_f_ops[2] = {{.owner =		THIS_MODULE,.write =		snd_pcm_write,.aio_write =		snd_pcm_aio_write,.open =			snd_pcm_playback_open,.release =		snd_pcm_release,.llseek =		no_llseek,.poll =			snd_pcm_playback_poll,.unlocked_ioctl =	snd_pcm_playback_ioctl,.compat_ioctl = 	snd_pcm_ioctl_compat,.mmap =			snd_pcm_mmap,.fasync =		snd_pcm_fasync,.get_unmapped_area =	snd_pcm_get_unmapped_area,},{.owner =		THIS_MODULE,.read =			snd_pcm_read,.aio_read =		snd_pcm_aio_read,.open =			snd_pcm_capture_open,.release =		snd_pcm_release,.llseek =		no_llseek,.poll =			snd_pcm_capture_poll,.unlocked_ioctl =	snd_pcm_capture_ioctl,.compat_ioctl = 	snd_pcm_ioctl_compat,.mmap =			snd_pcm_mmap,.fasync =		snd_pcm_fasync,.get_unmapped_area =	snd_pcm_get_unmapped_area,}
};

 至此,machine部分的任务已经完成。

 

4. 字符设备注册

在sound/core/sound.c中有alsa_sound_init()函数,register_chrdev中的参数major与之前创建pcm设备是device_create时的major是同一个,这样的结果是,当应用程序open设备文件/dev/snd/pcmCxDxp时,会进入snd_fops的open回调函数,该open函数以次设备号为索引,从snd_minors全局数组中取出当初注册conrol、pcm设备时填充的snd_minor结构,然后从snd_minor结构中取出control、pcm设备的f_ops,并且把file->f_op替换为pcm设备的f_ops,紧接着直接调用pcm设备的f_ops->open()...

#define CONFIG_SND_MAJOR	116	/* standard configuration */
static int major = CONFIG_SND_MAJOR;static const struct file_operations snd_fops =
{.owner =	THIS_MODULE,.open =		snd_open,.llseek =	noop_llseek,
};alsa_sound_initregister_chrdev(major, "alsa", &snd_fops)

调用过程我们在下一篇文章再来详细介绍。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384494.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASOC调用过程

上一篇文章我们将了嵌入式系统注册声卡的过程&#xff1a;https://blog.csdn.net/qq_37659294/article/details/104748747 这篇文章我们以打开一个声卡的播放节点为例&#xff0c;讲解一下在APP调用open时&#xff0c;最终会如何调用到硬件相关的函数。 在上一篇文章最后我们说…

进程上下文与中断上下文的理解

一.什么是内核态和用户态 内核态&#xff1a;在内核空间执行&#xff0c;通常是驱动程序&#xff0c;中断相关程序&#xff0c;内核调度程序&#xff0c;内存管理及其操作程序。 用户态&#xff1a;用户程序运行空间。 二.什么是进程上下文与中断上下文 1.进程上下文&#xf…

内核的Makefile与Kconfig关系解析

在子目录下的Kconfig里添加make menuconfig的选项&#xff08;如图一&#xff09;&#xff0c;并默认设置为y&#xff0c;make menuconfig的菜单里就会有该项并默认为选上状态&#xff0c;make menuconfig配置完之后在.config文件里就有该选项&#xff0c;并等于y&#xff08;如…

Linux信号之signal函数

1. 信号概述 何为信号&#xff1a;信号就是由用户、系统或进程发送给目标进程的信息&#xff0c;以通知目标进程中某个状态的改变或是异常。 信号产生&#xff1a;总体来说&#xff0c;其产生的条件有两种&#xff0c;分别是&#xff1a;硬件和软件原因&#xff0c;又称为&…

Linux中wait()函数及waitpid()函数

编程过程中&#xff0c;有时需要让一个进程等待另一个进程&#xff0c;最常见的是父进程等待自己的子进程&#xff0c;或者父进程回收自己的子进程资源包括僵尸进程。这里简单介绍一下系统调用函数&#xff1a;wait() 函数原型是 #include <sys/types.h> #include <…

学习笔记 --- DM9000网卡原理与基地址设置

前面有文章分析了网卡也是属于类内存总线的设备&#xff0c;类内存总线的设备有地址总线和数据总线&#xff0c;先来看下DM9000的管脚&#xff1a; 从上面可以看出DM9000的地址总线就一根&#xff0c;它不像CS8900那样地址总线和数据总线都齐全。而这里只有一根地址线(CMD)&…

静态VLAN的配置

在一台交换机上连接3台PC机&#xff0c;然后创建两个VLAN&#xff0c;分别为VLAN 10 和VLAN 20&#xff0c;把第一台PC机分配给VLAN 10&#xff0c;把其他两台分配给VLAN 20.然后测试他们的互通情况。 在这里命令我用的都是简化命令&#xff0c;想卡完整版命令&#xff0c;请到…

静态路由原理

1、路由器的工作原理 路由工作简单原理图 1&#xff09;主机1.1要发生数据包给主机4.1.因为IP地址不在同一网段&#xff0c;所以主机会将数据包发送给本网段的网关路由器。 2&#xff09;路由器A 接收到数据包&#xff0c;先查看数据包IP首部中的目标IP地址。再查找自己的路由表…

静态路由和默认路由

一、静态路由的配置 下边实验对该拓扑图进行配置 实验目标&#xff1a;配置静态路由&#xff0c;实现全网互通 1、配置路由器R1 进入接口f0/0&#xff0c;配置IP&#xff0c;并开启。 进入接口f0/1&#xff0c;配置IP&#xff0c;并开启。 设置静态路由。 查看PC1的路由表 2、配…

IP地址192.168.1.1/24中的/24是什么意思

/24是指子网掩码的位数。 子网掩码的位数总共有32个&#xff0c;写的的/24个就是24个1&#xff0c;其它8位都是0。 /24就可以写成子网掩码是&#xff1a;11111111 11111111 11111111 00000000 例如&#xff1a; /25&#xff0c;就代表有25个1&#xff0c;7个0&#xff0c;…

IP地址中A类、B类、C类地址的区别

区别如下&#xff1a; 1、IP地址表示方法不同&#xff1a; 一个A类IP地址是指&#xff0c; 在IP地址的四段号码中&#xff0c;第一段号码为网络号码&#xff0c;剩下的三段号码为本地计算机的号码。如果用二进制表示IP地址的话&#xff0c;A类IP地址就由1字节的网络地址和3字…

原始套接字简介

一 原始套接字概述 原始套接字&#xff0c;指在传输层下面使用的套接字。流式套接字和数据报套接字这两种套接字工作在传输层&#xff0c;主要为应用层的应用程序提供服务&#xff0c;并且在接收和发送时只能操作数据部分&#xff0c;而不能对IP首部或TCP和UDP首部进行操作&am…

TCP socket心跳包示例程序

TCP socket心跳包示例程序_xqhrs232的专栏-CSDN博客_setsockopt 心跳包 原文地址::TCP socket心跳包示例程序_神奕的专栏-CSDN博客_tcp心跳包 相关文章 1、Linux网络编程--服务端判断客户端断开的经验方法 ----Linux网络编程--服务端判断客户端断开的经验方法_志存高远-CSDN博…

sizeof()计算结构体的大小

原文链接&#xff1a;sizeof()计算结构体的大小_海月汐辰-CSDN博客_结构体的sizeof怎么计算 简要说明&#xff1a;结构体成员按照定义时的顺序依次存储在连续的内存空间&#xff0c;但是结构体的大小并不是简单的把所有成员大小相加&#xff0c;而是遵循一定的规则&#xff0c…

select、poll、epoll使用小结

转载&#xff1a;http://blog.csdn.net/kkxgx/article/details/7717125 Linux上可以使用不同的I/O模型&#xff0c;我们可以通过下图了解常用的I/O模型&#xff1a;同步和异步模型&#xff0c;以及阻塞和非阻塞模型&#xff0c;本文主要分析其中的异步阻塞模型。 一、select使用…

Qt报错:undefined reference to xxxxx

报错信息&#xff1a; 首先&#xff0c;要区分与undefined reference to xxxxx和 "xxxx was not declared in this scope"两种报错信息的差别&#xff0c;前者是因为编译器能找到函数的声明&#xff0c;但是找不到函数的定义&#xff0c;从而报错&#xff1b;而后者是…

对象的浅拷贝和深拷贝

对象的浅拷贝和深拷贝简要介绍代码实现简要介绍 浅拷贝&#xff1a;python拷贝一般都是浅拷贝。拷贝时&#xff0c;对象包含的子对象内容不拷贝。因此&#xff0c;源对象和拷贝对象引用同一个对象 深拷贝&#xff1a;使用copy模块的deepcopy函数&#xff0c;递归拷贝对象中包含…

用模板写单链表

转载自&#xff1a;http://blog.csdn.net/itcastcpp/article/details/39081953 为了加深对模板的理解&#xff0c;我们今天一起用模板写一个单链表&#xff0c;希望通过这个例子&#xff0c;能够帮助大家加深对模板的体会&#xff0c;具体如下&#xff1a; SList.hpp内容&#…

QT事件事件之一:Qt中的事件处理与传递

QT事件事件之一&#xff1a;Qt中的事件处理与传递前言一、简介二、QT中的事件三、事件的实现的方法前言 在QT中&#xff0c;事件是我们很常用的东西&#xff0c;以下是我用事件时总结和做法 一、简介 在QT中&#xff0c;事件作为一个对象&#xff0c;继承QEvent类&#xff0c…

linux下成功安装ffmpeg( 亲测有效 )

linux下成功安装ffmpeg&#xff08; 亲测有效 &#xff09;一、下载二、安装步骤1.安装yasm2.安装ffmpeg总结一、下载 ffmpeg 官网下载&#xff1a; http://ffmpeg.org/download.html 安装yasm 官网下载&#xff1a;http://yasm.tortall.net/Download.html 二、安装步骤 1.…