{"id":4695,"date":"2021-07-19T11:39:30","date_gmt":"2021-07-19T02:39:30","guid":{"rendered":"https:\/\/now0930.pe.kr\/wordpress\/?p=4695"},"modified":"2021-07-19T11:49:27","modified_gmt":"2021-07-19T02:49:27","slug":"workqueue-%ec%8b%a4%ec%8a%b5","status":"publish","type":"post","link":"https:\/\/now0930.pe.kr\/wordpress\/workqueue-%ec%8b%a4%ec%8a%b5\/","title":{"rendered":"workqueue \uc2e4\uc2b5"},"content":{"rendered":"\n<p>\ub9ac\ub205\uc2a4\uac00 work queue\ub97c \ub2e4\uc591\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4. \ub098\ub294 \ucd08\uc9dc\ub77c DECLARE_WORK\uc640 INIT_WORK\ub97c \uad6c\ubd84\ud560 \uc218 \uc5c6\uc5c8\ub2e4. DECLARE_WORK\uac00 work struct\ub97c \uc804\uc5ed \ubcc0\uc218\ub85c \uc120\uc5b8\ud55c\ub2e4. \uc5ec\ub7ec work\ub85c \uac19\uc740 \ub370\uc774\ud130\uc5d0 \uc811\uadfc\ud560 \uc218 \uc788\ub2e4.  workqueue funtion() \ud30c\ub77c\ubbf8\ud130\ub85c work struct\ub97c \ub123\ub294\ub370, \uc5ec\uae30\ub85c work\ub97c \uc804\ub2ec\ud558\uba74 \ub41c\ub2e4. \ucf54\ub4dc\uac00 \ub11d\ub9c8\uc870\uac01\uc774 \ub418\uace0 \uc788\ub2e4.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1600\" src=\"https:\/\/now0930.pe.kr\/wordpress\/wp-content\/uploads\/2021\/07\/20210718_224421-edited-scaled.jpg\" alt=\"\" class=\"wp-image-4704\" srcset=\"https:\/\/now0930.pe.kr\/wordpress\/wp-content\/uploads\/2021\/07\/20210718_224421-edited-scaled.jpg 2560w, https:\/\/now0930.pe.kr\/wordpress\/wp-content\/uploads\/2021\/07\/20210718_224421-edited-2048x1280.jpg 2048w, https:\/\/now0930.pe.kr\/wordpress\/wp-content\/uploads\/2021\/07\/20210718_224421-edited-768x480.jpg 768w, https:\/\/now0930.pe.kr\/wordpress\/wp-content\/uploads\/2021\/07\/20210718_224421-edited-1536x960.jpg 1536w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><\/figure>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include &lt;linux\/module.h>\n#include &lt;linux\/kernel.h>\n#include &lt;linux\/init.h>\n#include &lt;linux\/irq.h>\n#include &lt;linux\/interrupt.h>\n#include &lt;linux\/gpio.h>     \/\/GPIO\n\n\n#include &lt;linux\/cdev.h>\n#include &lt;linux\/device.h>\n#include &lt;linux\/uaccess.h>\n#include &lt;linux\/fcntl.h>\n\n\n#include &lt;linux\/workqueue.h>\n\n#define GPIO_10_OUT (10)\n#define DEVICE_DATA_MAX 256\n\nunsigned int GPIO_irqNumber;\n\n\/*\\uc0ac\\uc6a9\\uc790 \\ub370\\uc774\\ud130 \\ubd80\\ubd84*\/\nstatic struct my_device_data{\n\tstruct cdev cdev;\n\tint index;\n\tchar my_string[DEVICE_DATA_MAX];\n\tstruct work_struct mywork;\n\tstruct work_struct work_read;\n} my_data_global;\n\nstruct my_device_data *work_ptr;\nstruct my_device_data *work_ptr_read;\nstruct my_device_data *my_data;\n\n\/*workque initiate*\/\n\nvoid workqueue_fn(struct work_struct *work);\n\n\/\/defien workqueue_fn\/\/\n\nvoid workqueue_fn(struct work_struct *work_ptr)\n{\n\t\/*work_ptr\\ub85c \\uc0ac\\uc6a9\\uc790 \\uc815\\uc758 \\ub370\\uc774\\ud130 \\uc811\\uadfc*\/\n\tstruct my_device_data *my_pointer;\n\t\/\/container of \\ub85c \\uc0ac\\uc6a9\\uc790 \\ub370\\uc774\\ud130 \\uc811\\uadfc.\n\tmy_pointer = container_of(work_ptr, struct my_device_data, mywork);\n\tmy_pointer->index++;\n\tpr_info(\"Executing workqueue function\\n\");\n\tpr_info(\"index is %d\\n\",my_pointer->index);\n\n}\n\n\nvoid workqueue_read(struct work_struct *work_ptr)\n{\n\t\/*work_ptr\\ub85c \\uc0ac\\uc6a9\\uc790 \\uc815\\uc758 \\ub370\\uc774\\ud130 \\uc811\\uadfc*\/\n\tstruct my_device_data *my_pointer;\n\t\/\/container of \\ub85c \\uc0ac\\uc6a9\\uc790 \\ub370\\uc774\\ud130 \\uc811\\uadfc.\n\tmy_pointer = container_of(work_ptr, struct my_device_data, work_read);\n\tmy_pointer->index++;\n\tpr_info(\"opened, index is %d\\n\", my_pointer->index);\n\n}\n\nstatic irqreturn_t gpio_irq_handler(int irq, void *dev_id)\n{\n\t\/*Scheduling work queue*\/\n\tschedule_work(&amp;work_ptr->mywork);\n\tpr_info(\"workqueue scheduled \\n\");\n\treturn IRQ_HANDLED;\n\n}\n\n\n\/\/device driver \\uc791\\uc131 \\ubd80\\ubd84.\n\/*************\\ub4dc\\ub77c\\uc774\\ubc84 \\ud568\\uc218 ******************\/\nstatic int mydriver_open(struct inode *inode, struct file *file);\nstatic int mydriver_release(struct inode *inode, struct file *file);\nstatic ssize_t mydriver_read(struct file *flip,\n\t\tchar *buf, size_t len, loff_t *off);\nstatic ssize_t mydriver_write(struct file *flip,\n\t\tconst char *buf, size_t len, loff_t *off);\n\/********************************************\/\n\n\n\n\/\/file operation structure\n\nstatic struct file_operations fops = \n{\n\t.owner = THIS_MODULE,\n\t.read = mydriver_read,\n\t.write = mydriver_write,\n\t.open = mydriver_open,\n\t.release = mydriver_release,\n};\n\nstatic int mydriver_open(struct inode *inode, struct file *file)\n{\n\tpr_info(\"Deviced file was opend.\\n\");\n\t\/\/my_data_global.index++;\n\t\n\treturn 0;\n\n}\n\nstatic int mydriver_release(struct inode *inode, struct file *file)\n{\n\tpr_info(\"Deviced file was closed.\\n\");\n\treturn 0;\n}\n\n\nstatic int mydriver_read(struct file *file,\n\t\tchar *buf, size_t len, loff_t *off)\n{\n\tstruct my_device_data *my_data;\n\tsize_t datalen, read_len;\n\tmy_data = (struct my_device_data*)&amp;my_data_global;\n\tdatalen = strlen(my_data->my_string);\n\t\/\/\\ucd5c\\ub300\\uac12\\uc73c\\ub85c \\uac15\\uc81c \\uc124\\uc815\n\tif(len > datalen)\n\t{\n\t\tlen = datalen;\n\t}\n\tread_len = len - *off;\n\tif (read_len &lt;= 0)\n\t\treturn 0;\n\tpr_info(\"start %p, offset is %lld, read_len is %d\\n\", my_data->my_string, *off, read_len);\n\tif(copy_to_user(buf, my_data->my_string+*off, read_len))\n\t\treturn -EFAULT;\n\t\/\/read_len = datalen-*off;\n\t*off += read_len;\n\tpr_info(\"kernel has %d, read %d characters from kernel\\n\", datalen, read_len);\n\t\/\/zero\\ub97c \\ubc18\\ud658\\ud560 \\ub54c\\uae4c\\uc9c0 \\ubc18\\ubcf5.\n\tschedule_work(&amp;work_ptr->work_read);\n\treturn read_len;\n}\n\nstatic int mydriver_write(struct file *flip,\n\t\tconst char *buf, size_t len, loff_t *off)\n{\n\tsize_t datalen, write_len, start_pos;\n\tmy_data = &amp;my_data_global;\n\tstart_pos = strlen(my_data->my_string);\n\tdatalen = strlen(my_data->my_string);\n\tif(len > datalen)\n\t{\n\t\tlen = DEVICE_DATA_MAX;\n\t}\n\n\twrite_len = len - *off;\n\n\tif(copy_from_user(my_data->my_string + start_pos + *off, buf, write_len))\n\t\treturn -EFAULT;\n\t*off += write_len;\n\treturn write_len;\n}\n\ndev_t dev = 0;\nstatic struct cdev my_cdev;\nstatic struct class *dev_class;\nstatic int __init init_hw(void)\n{\n\t\/\/\\ub514\\ubc14\\uc774\\uc2a4 \\ub4f1\\ub85d\n\tif(( alloc_chrdev_region(&amp;dev, 0, 1, \"test_device\") &lt; 0))\n\t{\n\t\tpr_err(\"[!]character device was not allocated\\n\");\n\t\tgoto r_unreg;\n\n\t}\n\tpr_info(\"[=]%d-%d, was allocated\\n\", MAJOR(dev), MINOR(dev));\n\n\n\t\/\/\\ucd08\\uae30\\ud654\n\tcdev_init(&amp;my_cdev, &amp;fops);\n\tpr_info(\"[=]driver was initialized\\n\");\n\n\n\t\/\/\\uc2dc\\uc2a4\\ud15c\\uc5d0 \\ucd94\\uac00\n\tif((cdev_add(&amp;my_cdev, dev, 1)) &lt; 0)\n\t{\n\t\tpr_err(\"[!]cannot add device to kernel\\n\");\n\t\tgoto r_del;\n\n\t}\n\n\n\t\/\/class \\ub9cc\\ub4e6.\n\tif((dev_class=class_create(THIS_MODULE, \"my_class\")) == NULL)\n\t{\n\t\tpr_err(\"[!]cannot add class\\n\");\n\t\tgoto r_class;\n\t}\n\n\n\tif((device_create(dev_class, NULL, dev, NULL, \"my_device\")) == NULL)\n\t{\n\n\t\tpr_err(\"[!]cannot create device\\n\");\n\t\tgoto r_device;\n\t}\n\twork_ptr = kmalloc(sizeof(*work_ptr), GFP_KERNEL);\n\tif(work_ptr == NULL)\n\t{\n\t\tpr_err(\"[!]cannot allocate memory\\n\");\n\t\tgoto r_work;\n\t}\n\tINIT_WORK(&amp;work_ptr->mywork, workqueue_fn);\n\n\n\n\t\/\/work_ptr_read = kmalloc(sizeof(*work_ptr), GFP_KERNEL);\n\tINIT_WORK(&amp;work_ptr->work_read, workqueue_read);\n\n\t\/\/gpio 10\\ubc88\\uc744 \\uc0ac\\uc6a9.\n\t\/\/export\\ud558\\uc5ec \\uac04\\ub2e8\\ud788 \\uc0ac\\uc6a9.\n\t\/\/\\uc785\\ub825\\uc740 \\uac12\\uc744 \\uc368 \\ub123\\uc744 \\uc218 \\uc5c6\\uc74c. \\ucd9c\\ub825\\uc73c\\ub85c \\uc124\\uc815.\n\tGPIO_irqNumber = gpio_to_irq(GPIO_10_OUT);\n\tpr_info(\"[=]irq %d was assinged\\n\",GPIO_irqNumber);\n\n\t\/\/interrupt \\ub4f1\\ub85d \\ud544\\uc694\n\tif (request_irq(GPIO_irqNumber,\n\t\t\t\t(void*)gpio_irq_handler,\n\t\t\t\tIRQF_TRIGGER_RISING,\n\t\t\t\t\"my_device\",\n\t\t\t\tNULL))\n\t{\n\t\tpr_err(\"[!]my_device: cannot register IRQ\\n\");\n\t\tgoto r_gpio;\n\t}\n\tpr_info(\"[=]module was installed\\n\");\n\treturn 0;\nr_gpio:\n\tgpio_free(GPIO_10_OUT);\nr_device:\n\tdevice_destroy(dev_class,dev);\n\nr_class:\n\tclass_destroy(dev_class);\nr_del:\n\tcdev_del(&amp;my_cdev);\n\nr_unreg:\n\tunregister_chrdev_region(dev,1);\nr_work:\n\tkfree(work_ptr);\n\n\treturn -1;\n}\n\nstatic void __exit exit_hw(void) {\n\tfree_irq(GPIO_irqNumber, NULL);\n\tgpio_free(GPIO_10_OUT);\n\t\/\/flush_work(struct work_struct *work);\n\tdevice_destroy(dev_class,dev);\n\t\/\/class_unregister(dev_class);\n\tclass_destroy(dev_class);\n\tcdev_del(&amp;my_cdev);\n\tunregister_chrdev_region(dev,1);\n\tflush_work(&amp;work_ptr->mywork);\n\tkfree(work_ptr);\n\tprintk(KERN_INFO \"module was removed\\n\");\n}\n\n\nmodule_init(init_hw);\nmodule_exit(exit_hw);\nMODULE_LICENSE(\"GPL\");\nMODULE_AUTHOR(\"noname\");\nMODULE_DESCRIPTION(\"Hello, world!\");\n<\/pre>\n\n\n\n<p>\ubaa8\ub4c8\uc744 \ub85c\ub529\ud558\uace0 \uc778\ud130\ub7fd\ud2b8\ub97c \ub9cc\ub4e4\uba74 schedule_work\ub85c \ub4f1\ub85d\ud55c workqueue_fn\uc744 \uc2e4\ud589\ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[   52.456926] [=]236-0, was allocated\n[   52.456935] [=]driver was initialized\n[   52.457621] [=]irq 54 was assinged\n[   52.457693] [=]module was installed\n[   68.542830] workqueue scheduled \n[   68.542855] Executing workqueue function\n[   68.542866] index is 1\n[   69.549436] workqueue scheduled \n[   69.549460] Executing workqueue function\n[   69.549466] index is 2\n[   70.552638] workqueue scheduled \n[   70.552659] Executing workqueue function\n[   70.552663] index is 3<\/pre>\n\n\n\n<p>\ud30c\uc77c\uc744 \uc624\ud508\ud558\uba74 \uac19\uc740 \ub370\uc774\ud130\ub97c \ub2e4\ub978 work\ub85c index\ub97c \uc811\uadfc\ud560 \uc218 \uc788\ub2e4. schedule_work(&amp;work_ptr-&gt;work_read)\ub97c \ub514\ubc14\uc774\uc2a4\ub97c \uc77d\uc744 \ub54c\ub9c8\ub2e4 \uc2e4\ud589\ud55c\ub2e4.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[   86.495196] Deviced file was opend.\n[   86.495242] Deviced file was closed.\n[   91.476276] Deviced file was opend.\n[   91.476318] start 9f3ac859, offset is 0, read_len is 5\n[   91.476327] kernel has 5, read 5 characters from kernel\n[   91.476367] opened, index is 4\n[   91.476430] Deviced file was closed.\n[  105.664089] Deviced file was opend.\n[  105.664138] start 9f3ac859, offset is 0, read_len is 5\n[  105.664149] kernel has 5, read 5 characters from kernel\n[  105.664197] opened, index is 5\n[  105.664275] Deviced file was closed.<\/pre>\n\n\n\n<p><a href=\"https:\/\/www.programmersought.com\/article\/61671813037\/\">https:\/\/www.programmersought.com\/article\/61671813037\/<\/a><\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-link is-provider-learning-c-by-example wp-block-embed-learning-c-by-example\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"j9mDWvZ9ws\"><a href=\"https:\/\/jlmedina123.wordpress.com\/2016\/05\/18\/workqueue\/\">Workqueue<\/a><\/blockquote><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; visibility: hidden;\" title=\"&#8220;Workqueue&#8221; &#8212; Learning C by example\" src=\"https:\/\/jlmedina123.wordpress.com\/2016\/05\/18\/workqueue\/embed\/#?secret=zKqoM0tTgG#?secret=j9mDWvZ9ws\" data-secret=\"j9mDWvZ9ws\" width=\"500\" height=\"282\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n\n\n\n<p><a href=\"https:\/\/stackoverflow.com\/questions\/7937245\/how-to-use-linux-work-queue\/7938990\">https:\/\/stackoverflow.com\/questions\/7937245\/how-to-use-linux-work-queue\/7938990<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/fervagar\/kernel_modules\/blob\/master\/workQueue.c\">https:\/\/github.com\/fervagar\/kernel_modules\/blob\/master\/workQueue.c<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\ub9ac\ub205\uc2a4\uac00 work queue\ub97c \ub2e4\uc591\ud558\uac8c \uc0ac\uc6a9\ud55c\ub2e4. \ub098\ub294 \ucd08\uc9dc\ub77c DECLARE_WORK\uc640 INIT_WORK\ub97c \uad6c\ubd84\ud560 \uc218 \uc5c6\uc5c8\ub2e4. DECLARE_WORK\uac00 work struct\ub97c \uc804\uc5ed \ubcc0\uc218\ub85c \uc120\uc5b8\ud55c\ub2e4. \uc5ec\ub7ec work\ub85c [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4700,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[12],"tags":[53,798,934,912],"class_list":["post-4695","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-12","tag-linux","tag-raspberry","tag-workqueue","tag-912"],"jetpack_featured_media_url":"https:\/\/now0930.pe.kr\/wordpress\/wp-content\/uploads\/2021\/07\/2021-07-19-113104_1920x1080_scrot-e1626662172786.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/posts\/4695","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/comments?post=4695"}],"version-history":[{"count":5,"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/posts\/4695\/revisions"}],"predecessor-version":[{"id":4705,"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/posts\/4695\/revisions\/4705"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/media\/4700"}],"wp:attachment":[{"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/media?parent=4695"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/categories?post=4695"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/now0930.pe.kr\/wordpress\/wp-json\/wp\/v2\/tags?post=4695"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}