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.pswp.cn/news/384494.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384494.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384494.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ASOC調用過程

上一篇文章我們將了嵌入式系統注冊聲卡的過程&#xff1a;https://blog.csdn.net/qq_37659294/article/details/104748747 這篇文章我們以打開一個聲卡的播放節點為例&#xff0c;講解一下在APP調用open時&#xff0c;最終會如何調用到硬件相關的函數。 在上一篇文章最后我們說…

編寫聲卡驅動(框架)

在前面兩篇文章中&#xff0c;我們分別講了嵌入式Linux系統聲卡注冊的過程和調用的過程&#xff1a; https://blog.csdn.net/qq_37659294/article/details/104748747 https://blog.csdn.net/qq_37659294/article/details/104802868 講了那么多&#xff0c;我們最終的目的無非…

聲卡學習筆記

分享幾篇關于韋東山聲卡驅動的學習筆記&#xff0c;作者寫得非常詳細。 ALSA驅動框架&#xff1a;https://blog.csdn.net/qingkongyeyue/article/details/52328991 ASoC驅動框架&#xff1a;https://blog.csdn.net/qingkongyeyue/article/details/52349120 ASoC驅動重要結構…

路由器、交換機、集線器的區別

https://blog.csdn.net/weibo1230123/article/details/82779040

$PATH環境變量的作用

echo $PATH 顯示當前PATH環境變量&#xff0c;該變量的值由一系列以冒號分隔的目錄名組成&#xff0c;如&#xff1a;/usr/local/bin:/bin:/usr/bin。(冒號:是路徑分隔符) 在執行一個程序的時候如果沒有PATH的話&#xff0c;就需要寫出路徑名&#xff08;絕對或者相對&#xf…

dmesg

https://blog.csdn.net/zm_21/article/details/31760569

進程上下文與中斷上下文的理解

一.什么是內核態和用戶態 內核態&#xff1a;在內核空間執行&#xff0c;通常是驅動程序&#xff0c;中斷相關程序&#xff0c;內核調度程序&#xff0c;內存管理及其操作程序。 用戶態&#xff1a;用戶程序運行空間。 二.什么是進程上下文與中斷上下文 1.進程上下文&#xf…

GDB調試教程:1小時玩轉Linux gdb命令

原文鏈接&#xff1a;http://c.biancheng.net/gdb/ GDB 入門教程 本教程以下面的代碼為例&#xff0c;在 Linux 系統下來講解 GBD 的調試流程&#xff1a; int main (void) {unsigned long long int n, sum;n 1;sum 0;while (n < 100){sum sum n;n n 1;}return 0; …

shell將命令執行的結果賦值給 變量

https://blog.csdn.net/lemontree1945/article/details/79126819/

Linux下shell腳本指定程序運行時長

https://www.cnblogs.com/yychuyu/p/12626798.html

vim編輯器如何刪除一行或者多行內容

http://blog.itpub.net/69955379/viewspace-2681334/

C++經典問題:如果對象A中有對象成員B,對象B沒有默認構造函數,那么對象A必須在初始化列表中初始化對象B?

對象成員特點總結&#xff1a; &#xff08;1&#xff09;實例化對象A時&#xff0c;如果對象A有對象成員B,那么先執行對象B的構造函數&#xff0c;再執行A的構造函數。 &#xff08;2&#xff09;如果對象A中有對象成員B,那么銷毀對象A時&#xff0c;先執行對象A的析構函數&…

JZ2440用U-Boot給Nand-Flash燒寫程序時報錯:NAND write: incorrect device type in bootloader ‘bootloader‘ is not

JZ2440開發板使用問題&#xff0c;U-Boot燒寫程序到Nand Flash時報錯&#xff1a;NAND write: incorrect device type in bootloader bootloader is not a number 這是因為分區名中u-boot&#xff0c;不是bootloader&#xff0c;而cmd_menu.c里用的是bootloader 可以執行&#…

韋東山銜接班——4.4_構建根文件系統之構建根文件系統

文章地址&#xff1a; https://blog.csdn.net/gongweidi/article/details/100086289?biz_id102&utm_term%E9%9F%A6%E4%B8%9C%E5%B1%B1%E8%A1%94%E6%8E%A5%E7%8F%AD&utm_mediumdistribute.pc_search_result.none-task-blog-2~blog~sobaiduweb~default-5-100086289&…

C++中const char *p和char const *p

const char *p;他的意思是p指向的目標空間的內容不可變化 例如定義char cA; p&c;則c的內容不可以變化.如cB;等一些企圖改變變量c的值的做法都不行. 然而p仍然是動態的,就是它還可以指向別的空間,被賦予新的地址值,只是被他指向的目標空間的內容不可變化,如上面的c值始終為A…

qt 分割字符串的兩種方法

https://blog.csdn.net/a724699769/article/details/62216435

【YOLO系列】YOLOv3代碼詳解(五):utils.py腳本

前言 以下內容僅為個人在學習人工智能中所記錄的筆記&#xff0c;先將目標識別算法yolo系列的整理出來分享給大家&#xff0c;供大家學習參考。 本文僅對YOLOV3代碼中關鍵部分進行了注釋&#xff0c;未掌握基礎代碼的鐵汁可以自己百度一下。 若文中內容有誤&#xff0c;希望大家…

內核的Makefile與Kconfig關系解析

在子目錄下的Kconfig里添加make menuconfig的選項&#xff08;如圖一&#xff09;&#xff0c;并默認設置為y&#xff0c;make menuconfig的菜單里就會有該項并默認為選上狀態&#xff0c;make menuconfig配置完之后在.config文件里就有該選項&#xff0c;并等于y&#xff08;如…

C語言extern的用法

在x.c文件里定義如&#xff1a;int x 100; 在x.h文件里聲明如&#xff1a;extern int x; 然后在main.c里 #include "x.h"即可 或者直接在main.c里 extern int x; 而不使用#include "x.h"&#xff08;此時x.h里當然也不用extern int x;&#xff09;也…

C語言中.和->區別

結構體變量用 . 運算符來訪問結構體的成員 struct A { int a; int b; };A object; object.a 1;指向結構體的指針用->來訪問其指向的結構體的成員 A *point malloc(sizeof(struct A)); point->a 1;