{"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 class=\"wp-block-paragraph\">\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 class=\"wp-block-paragraph\">\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 class=\"wp-block-paragraph\">\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 class=\"wp-block-paragraph\"><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=\"v2eAkNt3fN\"><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=\"\u201cWorkqueue\u201d \u2014 Learning C by example\" src=\"https:\/\/jlmedina123.wordpress.com\/2016\/05\/18\/workqueue\/embed\/#?secret=sYZUcdCTes#?secret=v2eAkNt3fN\" data-secret=\"v2eAkNt3fN\" width=\"580\" height=\"327\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><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 class=\"wp-block-paragraph\"><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 \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. \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. \ud30c\uc77c\uc744 \uc624\ud508\ud558\uba74 \uac19\uc740 \ub370\uc774\ud130\ub97c \ub2e4\ub978 work\ub85c index\ub97c \uc811\uadfc\ud560 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4700,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"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_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/now0930.pe.kr\/wordpress\/wp-content\/uploads\/2021\/07\/2021-07-19-113104_1920x1080_scrot-e1626662172786.png","_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}]}}